Android應用開發—知識點彙總

image_c發表於2017-08-12
版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/voidreturn/article/details/77113335
  • 獲取Fragment的context:
   getActivity().getApplicationContext()或者getActivity()
   You can use getActivity(), which returns the activity associated with a fragment.
   The activity is a context (since Activity extends Context).
  • 設定TextView的顏色setTextColor()的用法:
 setTextColor(0xff999faa);
 setTextColor(Color.parseColor("#999faa"))
  • Android textView 動態設定字型大小,帶單位:
setTextSize(TypedValue.COMPLEX_UNIT_PX,22); 
setTextSize(TypedValue.COMPLEX_UNIT_SP,22); 
setTextSize(TypedValue.COMPLEX_UNIT_DIP,22);
  • 初始化一個ArrayList<>並賦值:
ArrayList<String> list = new ArrayList<String>() {{add("string1"); add("string2"); add("string3");}}
  • setBackgroundDrawable和setBackgroundResource的區別:
setBackgroundXXX的用處,設定View背景。
setBackgroundDrawable的引數為Drawable物件。
setBackgroundColor的引數為Color物件,比如說Color.Red為紅色或  Color.rgb(255,0,0)來指定一個紅色
setBackgroundResource的引數為資源ID,比如說R.drawable.icon

對於ImageView類有類似 setImageXXX
道理同上,setImageBitmap的引數為Bitmap物件,同時ImageView還支援矩陣物件,比如setImageMatrix的引數為Matrix物件。
  • Android延時執行介面:
new Handler().postDelayed(new Runnable(){
    @Override
    public void run() {
        func();
    }
}, 250);
  • 檢視Android系統服務命令:
adb shell service list
  • Activity有三種基本狀態:

    • Active:處於螢幕前景(當前task的棧頂Activity處於Active狀態),同一時刻只能有一個Activity處於Active狀態。
    • Paused狀態:處於背景畫面畫面狀態,失去了焦點,但依然是活動狀態。
    • Stopped:不可見,但依然保持所有的狀態和記憶體資訊。
  • 同一個Service的類在android中可以有多個例項嗎?
    不可以。Service的啟動模式決定它不會在系統中存在多個例項,當有新的Intent傳遞過來的時候,android系統會直接使用已經存在的Service例項而不會重新建立,所以在android系統中的Service都是單例的。

    但為什麼在錘子手機上有好幾個xstate service???

  • android繼承activity和application有什麼不同:
    初學安卓,看到有些程式碼繼承activity,有些繼承application,不知有什麼?
    Activty是UI介面的抽象,Application是應用程式的抽象。一個Application有若干個Activity組成。一般繼承Application主要是做一些初始化以及獲取全域性Context的引用,每個使用者介面都要繼承自Acitivity。

  • Fragment中呼叫startActivityForResult:
    注意要採用fragment的startActivityForResult,而不要通過activity呼叫,否則activity的onActivityResult回被回撥,fragment不會被呼叫,這樣start和onResult就分離了。
    目前還沒有遇到這個問題,先收藏著
    徹底搞懂startActivityForResult在FragmentActivity和Fragment中的異同
    淺談Android Fragment巢狀使用存在的一些BUG以及解決方法

  • 去除字串中的標點符號

public static String removePunct(String s) {
    String str = s.replaceAll("[`~!@#$%^&*()+=|{}`:;`,\[\].<>/?~!@#¥%……& amp;*()——+|{}【】‘;:”“’。,、?|-]", "");
    str = str.replace(""", "");
    return str;
}
  • 判斷字串中是否都是中文字元
public static boolean isChinese(String string) {
      String regex = "^[u4E00-u9FA5]+$";
      Pattern pattern = Pattern.compile(regex);
      Matcher match = pattern.matcher(string);
      return match.matches();
  }

“我在上一篇文章中曾說過,我並不喜歡Android中的Bundle,而且儘量避免使用它們。我不喜歡被象Serializable或者是Parcelable這類物件所約束,尤其是它們還缺少對型別安全的檢查。我的意思是必竟這是Java,而不是Python或者Javascript什麼的。我希望我的IDE能夠發現並告訴我這樣的錯誤,如一個元件向另外一個元件傳送了一個不是它期望的物件型別。
不要誤會,Intent在程式間通訊時還是很有用的,在這種情況下將攜帶的資料序列化成通用格式是合情合理的。但如果僅僅是為了在使用者旋轉了一下螢幕後,讓程式保持原來的狀態,以科學的名義說,有必要非得用這種方法麼?沒錯,我說的就是Android提供的處理配置改變的標準模式——在onSaveInstanceState(Bundle bundle)和onRestoreInstanceState(Bundle bundle)中儲存和恢復狀態資料。且不提那些荒唐複雜的Fragment生命週期問題,單單是保持執行狀態的這種處理方式就是我最不喜歡的Android開發特點之一。”

剛剛遇到了類似問題:Parcel android.os.Parcel@dbaf03f: Unmarshalling unknown type code 2131625126 at offset 1308 導致了crash

XXXX info = mXXXXList.get(position);
if (info == null) {
    return;
}
Intent intent = new Intent(XXXXActivity.this, XXXXActivity.class);
intent.putExtra(XXX.KEY_SOUND_INFO, info);

if (intent != null) {
    mXXXX = (XXXX) intent.getSerializableExtra(XXX.KEY_SOUND_INFO);
}

由於Serializable導致的問題,出現機率比較小,目前還沒找到原因。

  • AsyncTask, Loader和Executor…… 拜託!

摘錄自Android 中 EventBus 的使用(3):多執行緒事件處理

Android中有很多種執行非同步操作的方法(指平行於UI執行緒的)。AsyncTask對於使用者來說是最簡單的一種機制,並且只需要少量的設定程式碼即可。然而,它的使用是有侷限的,正如Android官方文件中所描述的:

AsyncTask被設計成為一個工具類,在它內部包含了Thread和Handler,但它本身並不是通用執行緒框架的一部分。AsyncTask應該儘可能地被用在執行一些較短的操作中(最多幾秒)。如果你需要線上程中執行較長時間的任務,那麼建議你直接使用java.util.concurrent包中提供的各種API,如Executor、 ThreadPoolExecutor以及FutureTask。

不過即便是執行短時間的操作也會帶來一些問題,特別是在與Activity/Fragment生命週期有關的地方。由於AsyncTask會持續地執行下去(即使啟動它們的Activity/Fragment已經被銷燬了)。這樣,一旦你在onPostExecute方法中試圖對UI進行更新,那麼最終將導致丟擲一個IllegalStateException異常。

Android 3.0中引入了Loader API用來解決Activity/Fragment生命週期的問題(它們的確很有效)。Loader API被設計成向Activity/Fragment中以非同步方式載入資料。儘管載入資料是一種非常常見的非同步操作,但並非唯一一種需要從UI執行緒中分開的操作。Loader還需要在Activity/Fragment中實現另外一個監聽介面。儘管這麼做沒有錯,但我個人並不喜歡這種模式(我的意思是最終你的程式碼中會包含許多的回撥函式,導致程式碼的可讀性變得很差)。最後,Activity和Fragment也並非唯一需要對非同步操作分執行緒的地方。例如如果在Service裡,你就不能訪問LoaderManager,所以最終你還是得使用AsyncTask或者java.util.concurrent。

java.util.concurrent包很不錯,我在Android和非Android專案中都可以使用。不過使用時需要對其進行多一點兒配置和管理,不象AsyncTask那麼簡單。你需要對ExecutorService進行初始化,管理和監視它的生命週期,並且可能需要跟一些Future物件打交道。

只要使用恰當,AsyncTask、 Loader和Executor都是非常有效的。但在複雜應用中,需要為每個任務選擇合適的工具,最終你可能三種都會用到。這樣你就得維護三種不同的處理併發的框架程式碼。

  • RelativeLayout佈局內元件設定居中
    備忘
android:layout_centerVertical="true"
  • 設定漸變色的背景
    設定背景色可以通過在res/drawable裡定義一個xml,如下:
xxx.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <item>
        <shape>
            <gradient
                android:angle="0"
                android:endColor="#28d5fa"
                android:startColor="#0083fa"
                android:type="linear" />
        </shape>
    </item>

</layer-list>

引用:

<RelativeLayout
                android:id="@+id/va_voice_print_step_ll"
                android:layout_width="match_parent"
                android:layout_height="149dp"
                android:background="@drawable/xxx">
</RelativeLayout>

shape:定義形狀(主要包括方形、圓形等);gradient:定義該形狀裡面為漸變色填充;startColor:起始顏色;endColor:結束顏色;angle:表示方向角度。(當angle=0時,漸變色是從左向右。 然後逆時針方向轉,當angle=90時為從下往上)。

gradient主要配置起點顏色、終點顏色、中間點的座標、中間點的顏色、漸變角度(90度為上下漸變,0為左右漸變);
padding主要配置上下左右邊距;
corners節點配置四周園角的半徑;
參考連結:Android (shape,gradient)使用總結android 背景漸變色(shape,gradient)

  • 如果在Android中判斷某個執行緒是否是主執行緒?
public static boolean isInMainThread() {
      return Looper.myLooper() == Looper.getMainLooper();
}
  • EditText中灰色文字提示
android:hint="請輸入xx"
  • 如何檢視Activity Task棧的情況
adb shell dumpsys activity activities
adb shell dumpsys activity top
  • 開啟app對應設定通知中心
public void openNotificationSettings() {
    try {
        Intent intent = new Intent();
        intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
            intent.putExtra("android.provider.extra.APP_PACKAGE", context.getPackageName());
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            intent.putExtra("app_package", context.getPackageName());
            intent.putExtra("app_uid", context.getApplicationInfo().uid);
        }
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • gradle裡面的cached module檔案位置
~/.gradle/caches/modules-2/files-2.1/com.ali*
  • 判斷app是否在前臺執行
 public boolean isAppOnForeground() {
    // Returns a list of application processes that are running on the
    // device

    ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
    String packageName = getApplicationContext().getPackageName();

    List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager
            .getRunningAppProcesses();
    if (appProcesses == null)
        return false;

    for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
        // The name of the process that this object is associated with.
        if (appProcess.processName.equals(packageName)
                && appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
            return true;
        }
    }
    return false;
}
  • Activity內使用Broadcast接收訊息

    大部分的Broadcast示例都是新建一個class繼承BroadcastReceiver來說明Broadcast的使用,但是這個class中接收到的訊息,如何進行後續處理呢?其實大部分情況下是希望在activity中通過Broadcast接收訊息,做一些後續的處理工作,而如果在一個新建的繼承自BroadcastReceiver的class中,如何和某個Activity通訊,這是一個悖論,訊息發生源傳遞給Broadcast,Broadcast再傳遞給Activity,後一步要採用什麼通訊方式呢?為什麼不訊息發生源不直接發生訊息給Activity呢?

    由於大部分示例都是在一個新的class中進行,導致我一度認為Broadcast只能寫在class裡。後來發現可以通過動態註冊的方式直接new一個BroadcastReceiver的方式,寫在Activity內部,由於BroadcastReceiver在Activity內部,BroadcastReceiver中onReceive()即可操作Activity內資料和控制元件,實現Activity接受訊息的目的。

private BroadcastReceiver mSearchRequestReceiver = new BroadcastReceiver() {
      @Override
      public void onReceive(Context context, Intent intent) {
          //do somethings
          }
      }
  };

  @Override
  public void onResume() {
      super.onResume();
      LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
      lbm.registerReceiver(mSearchRequestReceiver, new IntentFilter(SEARCH_REQUEST_BROADCAST_ACTION));
  }

  @Override
  protected void onPause() {
      super.onPause();
      LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
      lbm.unregisterReceiver(mSearchRequestReceiver);
  }
  • 判斷當前執行緒是否是Ui執行緒:
public static boolean isMainThread() {
        return Thread.currentThread() == Looper.getMainLooper().getThread();
}
  • Glide.with()使用
with(Context context):使用Application上下文,Glide請求將不受Activity/Fragment生命週期控制。
with(Activity activity):使用Activity作為上下文,Glide的請求會受到Activity生命週期控制。
with(FragmentActivity activity):Glide的請求會受到FragmentActivity生命週期控制。
with(android.app.Fragment fragment):Glide的請求會受到Fragment 生命週期控制。
with(android.support.v4.app.Fragment fragment):Glide的請求會受到Fragment生命週期控制。


相關文章