天天看點

Android 冷門知識點彙總:你知道哪些Android中的冷門知識?四大元件相關:Handler、Message相關:Window、View相關:Binder、IPC、程序等相關

Android 冷門知識點彙總:你知道哪些Android中的冷門知識?四大元件相關:Handler、Message相關:Window、View相關:Binder、IPC、程式等相關

四大元件相關:

1.啟動一個Activity,在應用程序至少需要兩個Binder線程。

2.啟動一個launchMode為singleTask的Activity,它并不一定會運作在新的Activity棧中。

3.兩個不同應用的Activity,可以運作在同一個Activity棧中。

4.同一個應用程序中的所有Activity,共享一個WindowSession。

5.彈出一個AlertDialog,不一定需要Activity級别的Context,而且任何地方都有辦法彈出一個AlertDialog,隻要是在Application的attachBaseContext之後。

下面是一個簡單的demo示範:

首先看DemoApplication,然後看Alert類:

在Application中初始化:
import android.app.Application;

public class DemoApplication extends Application {
    @Override
    public void onCreate() {
        Alert.alertAnyWhere();
        super.onCreate();
    }
}
           
下面這個類是對AlertDialog的封裝類:
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.view.WindowManager;
import java.lang.reflect.Method;

public class Alert {

    public static void alertDialog() {
        Context mAppContext = null;
        try {
            Class<?> clazz = Class.forName("android.app.ActivityThread");
            Method method = clazz.getDeclaredMethod("currentApplication", new Class[0]);
            mAppContext = (Context) method.invoke(null, new Object[0]);
        } catch (Throwable e) {
            e.printStackTrace();
            return;
        }

        AlertDialog.Builder builder = new AlertDialog.Builder(mAppContext);
        builder.setTitle("Hi")
               .setMessage("Hello World");
               .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                    }
                });
        AlertDialog dialog = builder.create();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST);
        } else {
            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);
        }
        dialog.show();
    }
           
private static Handler handler;

    public static void alertAnyWhere() {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            alertDialog();
        } else {
            if (handler == null) {
                handler = new Handler(Looper.getMainLooper());
            }
            handler.post(new Runnable() {
                @Override
                public void run() {
                    alertDialog();
                }
            });
        }
    }

}
           

6.可以通過設定Activity主題android.R.style.Theme_NoDisplay,來啟動一個不顯示的Activity,在某些需要過渡的地方很實用。

7.Activity、Service、Receiver在沒有配置intent-filter的action屬性時,exported預設為false,配置了intent-filter的action屬性時,exported預設為true。稍有不慎,很可能埋下越權、Intent攻擊等安全隐患。

8.當從最近使用應用清單中移除某個App時,四大元件隻有Service擁有神奇的onTaskRemoved回調,但是并不一定回調,還與stopWithTask屬性等有關。

9.四大元件都運作在主線程,是因為它們在ActityThread中(或Instrumentation)執行個體化;它們的生命周期也運作在主線程,是因為通過ActivityThread.H将消息從Binder線程發送到主線程,然後執行回調。

10.TaskStackBuilder的出現基本上解決了所有構造Activity回退棧的問題。

11.ContentProvider的onCreate()方法先于Application的onCreate()方法執行,晚于Application的attachBaseContext()方法,是以在ContentProvider的onCreate()時候也是有辦法彈出一個AlertDialog的(參考5)。

12.BroadCastReceiver回調onReceive(Context context,Intent intent)中的context類型各種場景相差很大,靜态注冊的receiver回調的Context都是ReceiverRestrictedContext,動态注冊的receiver有可能是Activity或Application。

13.ServiceRecord和BroadcastRecord自身就是Binder。

14.同一個provider元件名,可能對應多個provider。

Handler、Message相關:

1.MessageQueue.addIdleHandler可以用來線上程空閑的時候,完成某些操作,比較适合那種需要在将來執行操作,卻又不知道需要指定多少延遲時間的操作。

2.Message.what盡量不要設定成0,因為postRunnable的方式會生成Message.what為0的消息,如果删除了what為0的Message,也會将runnable方式建立的Message删掉。

3.Handler可以設定同步異步(預設是同步的),他們的差別在于異步不會被Barrier阻塞,而同步會被阻塞。

4.Handler的消息分發流程是如果Message的callback不為空,通過callback處理,如果Handler的mCallback不為空,通過mCallback來處理,如果前兩個都為空,才調用handleMessage來處理。在DroidPlugin中,便是利用ActivityThread.H的這一特性,攔截了部分消息,實作Activity的插件化。

5.Java層和Native層Looper、MessageQueue的建立時序,Java層Looper—>Java層MessageQueue—>Native層NativeMessageQueue—>Native層Looper。

6.Java層通過Handler去發送消息,而Native層是通過Looper發消息。

Window、View相關:

1.硬體加速在Window級隻能開不能關,View級隻能關不能開。

2.自android2.3删除MidWindow後,PhoneWindow成了Window的唯一實作類。

3.WMS管理Window的過程中涉及4個Binder,應用程序隻有ViewRootImpl.W一個Binder服務端。

4.MotionEvent、KeyEvent、DragEvent等具有相似的鍊式緩存,類似Message。

5.在View的狀态儲存、恢複過程中,ActionBar中所有View共享一個SparseArray容器,ContentView中所有View共享一個SparseArray容器。目前擷取焦點的View會額外存儲。

6.設定ViewTreeObserver的系列監聽方法需要確定View在attachToWindow之後,否則可能因為add監聽和remove監聽不是作用于同一個對象而引起記憶體洩漏等。

Binder、IPC、程序等相關

1.可以通過檔案鎖來實作程序間互斥(參考:RePlugin),在處理某些隻需要單程序執行的任務時很實用。

2.Binder設計架構中,隻有Binder主線程是由本程序主動建立,Binder普通線程都是由Binder驅動根據IPC通信需求被動建立。

3.oneway與非oneway,都需要等待Binder Driver的回應消息(BR_TRANSACTION_COMPLETE),差別在于oneway不用等待BR_REPLY消息。

4.mediaserver和servicemanager的主線程都是binder線程,但system_server的主線程不是Binder線程,system_server主線程的玩法跟應用程序一樣。

5.同一個BpBinder可以注冊多個死亡回調,但Kernel隻允許注冊一次死亡通知。

6.應用程序由Zygote程序孵化而來,在它真正成為應用程序之前,系統通過抛異常的方式來清理棧幀,并反射調用ActivityThread的main方法。

7.在Binder通信的過程中,資料是從發起通信程序的使用者空間直接寫到目标程序核心空間,核心空間的資料釋放是由使用者空間控制的。

好了,文章到這裡就結束了,如果你覺得文章寫得不錯就給個贊呗?如果你覺得那裡值得改進的,請給我留言。一定會認真查詢,修正不足。謝謝~

繼續閱讀