美文网首页
Activity的学习

Activity的学习

作者: David_zhou | 来源:发表于2020-05-09 11:24 被阅读0次

偶然翻到一片文章,用两张图告诉你,为什么你的App会卡顿?,写得很好,跟着这篇文章学习后准备自己做个笔记,用作备忘。

activity可以说是android里面最重要的类,是界面的呈现者,也是和系统交互的沟通桥梁。对于这个类,我们肯定会有很多问题,比如以下:

如何响应用户的输入

界面如何显示

activity的视图结构是怎样

如何和系统交互

下面先从父类接口和成员变量,方法等方面简单分析下activity这个类。最后我们尝试回答上面的几个问题。

activity的重要成员变量
private Instrumentation mInstrumentation;
    private IBinder mToken;
    private Application mApplication;
    private ComponentName mComponent;
    /*package*/ ActivityInfo mActivityInfo;
    /*package*/ ActivityThread mMainThread;
    Activity mParent;
    private Window mWindow;
    private WindowManager mWindowManager;
    final Handler mHandler = new Handler();
    final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
    private Thread mUiThread;

以上是activity的一部分重要的成员变量,从成员变量的类型来看activity很复杂,不过我们挑着重要的看一下。

Instrumentation这个类是负责和系统的交互,不过隐藏在背后。

Application用来保存一些全局的应用数据,也是app程序开发的入口。

ComponentName这个就是四大组件,在使用adb启动activity,service,BroadcastReceiver等组件时需要带上-n 就表示要启动ComponentName。

ActivityInfo这个类主要用来保存activity的一些数据,比如主题,启动模式,权限等固定信息。

ActivityThread是我们app程序的主线程,即UI线程。

Window 用来管理呈现的窗口,和界面有关系。

WindowManager 负责管理窗口及显示的内容

每一个成员变量都不简单,o(╥﹏╥)o。

父类及接口
父类

Activity的直接父类是ContextThemeWrapper,这个类不太熟。先看这个类的父类也就是ContextWrapper,ContextWrapper的父类是我们平时接触最多的是Context,总算有点熟悉了。context可以认为是给应用提供了各种和系统交互的能力,因此重要的application,activity,service等都是其子类。context的详细介绍参见这篇文章:深入理解 Android 中的各种 Context。activity因此就具备了和系统交互的能力,包括和四大组件的交互,资源、文件、主题等方法。

接口

LayoutInflater.Factory2 : 布局创建相关的,接口只有一个方法。

public interface Factory2 extends Factory {
     public View onCreateView(View parent, String name, Context context, AttributeSet attrs);
}

Window.Callback: 负责用户输入交互的,因此activity就具备和用户交互的能力。

public interface Callback {
        public boolean dispatchKeyEvent(KeyEvent event);
        public boolean dispatchKeyShortcutEvent(KeyEvent event);
        public boolean dispatchTouchEvent(MotionEvent event);
        public boolean dispatchTrackballEvent(MotionEvent event);
        public boolean dispatchGenericMotionEvent(MotionEvent event);
        public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event);
        @Nullable
        public View onCreatePanelView(int featureId);
        public boolean onCreatePanelMenu(int featureId, Menu menu);
        public boolean onPreparePanel(int featureId, View view, Menu menu);
        public boolean onMenuOpened(int featureId, Menu menu);
        public boolean onMenuItemSelected(int featureId, MenuItem item);
        public void onWindowAttributesChanged(WindowManager.LayoutParams attrs);
        public void onContentChanged();
        public void onWindowFocusChanged(boolean hasFocus);
        public void onAttachedToWindow();
        public void onDetachedFromWindow();
        public void onPanelClosed(int featureId, Menu menu);
        public boolean onSearchRequested();
        public boolean onSearchRequested(SearchEvent searchEvent);
        @Nullable
        public ActionMode onWindowStartingActionMode(ActionMode.Callback callback);
        @Nullable
        public ActionMode onWindowStartingActionMode(ActionMode.Callback callback, int type);
        public void onActionModeStarted(ActionMode mode);
        public void onActionModeFinished(ActionMode mode);
        default public void onProvideKeyboardShortcuts(
                List<KeyboardShortcutGroup> data, @Nullable Menu menu, int deviceId) { };
        default public void onPointerCaptureChanged(boolean hasCapture) { };
    }

KeyEvent.Callback: 处理按键相关的交互。

public interface Callback {
        boolean onKeyDown(int keyCode, KeyEvent event);
        boolean onKeyLongPress(int keyCode, KeyEvent event);
        boolean onKeyUp(int keyCode, KeyEvent event);
        boolean onKeyMultiple(int keyCode, int count, KeyEvent event);
    }

OnCreateContextMenuListener:菜单创建时的回调 ,不是很清楚 (¦3」∠)

public interface OnCreateContextMenuListener {
        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
    }

ComponentCallbacks2: 四大组件通用的回调,比如设置时的回调以及低内存时的操作。

public interface ComponentCallbacks2 {
    void onConfigurationChanged(Configuration newConfig);
    void onLowMemory();
    void onTrimMemory(@TrimMemoryLevel int level);
}

Window.OnWindowDismissedCallback: window消失时的操作。

public interface OnWindowDismissedCallback {
        void onWindowDismissed(boolean finishTask, boolean suppressWindowTransition);
    }

WindowControllerCallback:不是很清楚这个什么时候回调 ε=(´ο`*)))。

public interface WindowControllerCallback {
        void toggleFreeformWindowingMode() throws RemoteException;
        void enterPictureInPictureModeIfPossible();
        boolean isTaskRoot();
    }

AutofillManager.AutofillClient: 自动填写相关的功能。

public interface AutofillClient {
        void autofillClientAuthenticate(int authenticationId, IntentSender intent,
                Intent fillInIntent);
        void autofillClientResetableStateAvailable();
        boolean autofillClientRequestShowFillUi(@NonNull View anchor, int width, int height,
                @Nullable Rect virtualBounds, IAutofillWindowPresenter presenter);
        void autofillClientDispatchUnhandledKey(@NonNull View anchor, @NonNull KeyEvent keyEvent);
        boolean autofillClientRequestHideFillUi();
        boolean autofillClientIsFillUiShowing();
        @NonNull boolean[] autofillClientGetViewVisibility(@NonNull AutofillId[] autofillIds);
        boolean autofillClientIsVisibleForAutofill();
        boolean isDisablingEnterExitEventForAutofill();
        @NonNull View[] autofillClientFindViewsByAutofillIdTraversal(
                @NonNull AutofillId[] autofillIds);
        @Nullable View autofillClientFindViewByAutofillIdTraversal(@NonNull AutofillId autofillId);
        @Nullable View autofillClientFindViewByAccessibilityIdTraversal(int viewId, int windowId);
        void autofillClientRunOnUiThread(Runnable action);
        ComponentName autofillClientGetComponentName();
        @Nullable IBinder autofillClientGetActivityToken();
        boolean autofillClientIsCompatibilityModeEnabled();
        @Nullable AutofillId autofillClientGetNextAutofillId();
    }

activity继承自context这个类,具备了很多和系统交互的能力。然后还实现了一堆借口,因此也有了多个特定方面的能力。对于这么多接口,只能先有个概念,之后有需要再详细分析。

重要的方法
构造函数?

一般分析类的时候都是从构造方法开始,然后activity有点特殊,只有默认的构造方法。我们直接看下activity的创建,创建是在ActivityThread中,关键代码如下。

// ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }
   }

   //Instrumentation.java
   public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        String pkg = intent != null && intent.getComponent() != null
                ? intent.getComponent().getPackageName() : null;
        return getFactory(pkg).instantiateActivity(cl, className, intent);
    }

   //AppComponentFactory.java
   public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,
            @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Activity) cl.loadClass(className).newInstance();
    }

可以看到activity的创建是通过反射的方式,其实application和service的创建也是通过反射创建。activity,application等属于android中特有的类,不仅仅是普通的类,创建的时候还需要上下文等信息,不知道这个是不是通过反射创建的原因?

attach

在activity实例创建出来后随即调用了attach方法。

final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);

        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }
        mUiThread = Thread.currentThread();

        mMainThread = aThread;
        mInstrumentation = instr;
        mToken = token;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) {
            if (lastNonConfigurationInstances != null) {
                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
            } else {
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            }
        }

        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;

        mWindow.setColorMode(info.colorMode);

        setAutofillCompatibilityEnabled(application.isAutofillCompatibilityEnabled());
        enableAutofillCompatibilityIfNeeded();
    }

在这个方法中给重要的成员变量赋值了。

todo

1 为什么是通过反射的方式创建activity?

为什么

get

1 提出问题,带着问题去学习

参考链接:

用两张图告诉你,为什么你的App会卡顿?

深入理解 Android 中的各种 Context

相关文章

  • Activity的学习

    偶然翻到一片文章,用两张图告诉你,为什么你的App会卡顿?,写得很好,跟着这篇文章学习后准备自己做个笔记,用作备忘...

  • Activity学习

    简介: Activity是一个应用组件,用户可与其提供的屏幕进行交互,以执行拨打电话、拍摄照片、发送电子邮件等操作...

  • Activity学习

    Activity是Android中最重要的组件之一。它为应用提供了窗口与用户进行交互,我们设计的界面也是通过Act...

  • 无标题文章

    #插件化学习使用代理activity的方式,宿主内有个activity壳,宿主内启动壳activity,实际加载外...

  • Activity相关学习-finish activity

    前言 前面大致整理了startActivity的相关流程,下面整理下Activity finish相关的流程 Ac...

  • activity

    纯粹是个人学习总结,如有不对的地方请吐槽。 Activity的简单介绍 什么是Activity?activity是...

  • WD的Activity学习

    大多为《第一行代码代码》内容 1. Menu用法 [1] 在Menu目录下定义main.xml文件 [2] ...

  • Android零基础入门第78节:四大组件的纽带——Intent

    前面学习Activity时己经多次使用了 Intent,当一个Activity需要启动另一个Activity时, ...

  • Activity与Service交互(使用广播方式)

    近期学习到了Activity与Service进行交互的过程,在此记录。本次使用的Activity和Service交...

  • Fragment学习总结

    Fragment学习总结 Fragment:碎片。可以看成Activity的一个控件,必须依赖于Activity才...

网友评论

      本文标题:Activity的学习

      本文链接:https://www.haomeiwen.com/subject/lonhnhtx.html