Android面试知识点汇总(一)

Android基础

一、Activity相关

1.Activity生命周期

  • Activity是与用户交互的接口
  • Android系统通过Activity栈的形式来管理Activity
  • Active/Paused/Stopped/Killed

正常情况下回调方法:

  • onStart()回调表示可见但无法与用户交互。
  • onResume()回调表示处于前台,可见且可与用户交互。
  • onPause()表示正在停止,与onResume()成对出现。
  • onStop()在onPause()执行完以后立即执行,表示即将停止或完全由一个新的Activity覆盖,此时Activity不可见,只能在后台运行。
  • onCreate()与onDestroy()成对出现,前者进行初始化,后者做回收、资源释放工作。
  • onRestart()是当Activity由onStop()变为onStart()方法之间回调。

异常情况下(系统配置发生改变或内存不足等情况下,Activity异常终止时)系统回调方法:

  • onSaveInstanceState(Bundle outState)保存当前Activity状态信息,用此方法恢复数据是需进行Bundle非空判断。
  • onRestoreInstanceState(Bundle savedInstanceState),当Activity被重新创建后调用,Bundle为非空,不需进行非空判断。

总结

  1. Activity正常启动:onCreate-onStart-onResume
  2. 点击back回退:onPause-onStop-onDestroy
  3. 打开新的Activity:onPause-onStop
  4. Activity异常:onSaveInstanceState保存数据
  5. Activity重新创建:调用onRestoreInstanceState

2.Activity通信

Activity之间通信的三种方式:Intent/Bundle、类静态变量、全局变量

Activity与Fragment通信:Bundle、直接在Activity中定义方法

利用Bundle,Activity将数据传到依附它的Fragment上:

public class FragmentActivity1 extends Activity {
    public String productId;
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle bundle = new Bundle();
        bundle.putString(Constant.NTENT_D,productId);
        Fragment fragment = null;
        fragment.setArguments(bundle);
    }
}
public class Fragment1 extends Fragment {
    public String productId;
    @Override
    public void onStart() {
        super.onStart();
        if (isAdded()){//判断Fragment是否已经依附Activity
            productId = getArguments().getString(Constant.NTENT_D);
        }
    }
}

通过定义方法通信: 

public class FragmentActivity2 extends Activity {
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    public String getTitles(){
        return "getTitle";
    }
}
public class Fragment2 extends Fragment {
    public String titles;
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        titles = ((FragmentActivity2) activity).getTitle();
    }
}

Fragment与Activity通信:接口回调

  1. 在fragment中定义一个内部回调接口,使包含此fragment的Activity实现这个接口,则fragment可调用此接口传递数据
  2. 当fragment添加到Activity中时调用fragment生命周期方法中的onAttach()方法,可在此方法中检查相应Activity是否实现了fragment中定义的内部接口。即对它类型转换,赋值给fragment中对应的内部接口
  3. 调用onDetach时,要将传递进来的activity对象释放掉
public class Fragment3 extends Fragment implements View.OnClickListener{
    // 定义用来与外部activity交互,获取到宿主activity
    private FragmentListener listener;

    // 定义了所有activity必须实现的接口方法
    public interface FragmentListener {
        void process(String str);
    }

    // 当Fragment被加载到activity的时候会被回调


    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        if (activity instanceof FragmentListener) {
            listener = (FragmentListener)activity;
        } else {
            throw new IllegalArgumentException("activity must implement fragment interface");
        }
    }

    @Override
    public void onClick(View v) {
        listener.process("我是接口");
    }

    @Override
    public void onDetach() {
        super.onDetach();
        listener = null;
    }
}

二、事件分发机制

核心方法

  • dispatchTouchEvent()
  • onInterceptTouchEvent()
  • onTouchEvent()

Android面试知识点汇总(一)_第1张图片

1.Activity事件分发

Android面试知识点汇总(一)_第2张图片 Activity事件分发示意图

2.ViewGroup事件分发 

 

Android面试知识点汇总(一)_第3张图片 ViewGroup事件分发示意图

3.View事件分发 

 

Android面试知识点汇总(一)_第4张图片 View事件分发示意图

三、异步消息处理机制相关面试问题

1.Handler

Android面试知识点汇总(一)_第5张图片 Handler四大组件和运作机制

首先在主线程中为主线程创建Looper(Looper为线程持有),同时在Looper内部创建一个消息队列(MessageQueue对象)。当创建Handler时会取出当前线程的Looper,通过这个Looper不断轮询消息队列中的Message。Handler在子线程中发送消息的实质就是在MessageQueue中添加一条Message,最后通过Looper中的消息循环取得Message再交给Handler进行处理。

分析源码可知:

  • 创建Handler对象时如果Looper为空则会抛出异常。因为Handler发送消息必须发送到指定的消息队列中,而消息队列由Looper管理,所以创建Handler对象必须在当前线程中有指定Looper对象。
  • 消息队列核心方法为插入队列enqueueMessage()和读取和删除next(),内部由单链表实现。
  • 为确保每一个线程获取到的Looper都是唯一的,Looper.prepare()方法内部用sThreadLocal容器来保存Looper对象本身。ThreadLocal也称为线程本地变量,它为每个变量在每个线程都创建一个数据副本。

2.AsyncTask

Handler+线程池。使用线程池的主要原因是避免不必要的创建和销毁线程的开销。

分析源码可知:

  • 手机CPU核数(CPU_COUNT)+1作为AsyncTask线程使用的线程数核心(CORE_POOL_SIZE)大小,CPU核数*2+1作为线程池最线程数(MAXIMUM_POOL_SIZE)大小,线程池为静态。
  • 创建了ThreadFactory实例用于创建线程池,其中mCount变量为原子类型,为保证后面获得此数据时线程安全。
  • AsyncTask内部串行执行任务。
  • (未完待续)

你可能感兴趣的:(Android面试)