注:本文内容有自己理解部分,若有不对的地方,欢迎指出。

Android四大组件

Activity

什么是Activity?

是应用程序的组件,用于显示用户界面,可以与用户交互完成相关的操作。App中可以有很多个Activity。

Activity存储于android系统的返回栈(back stack)中,特点先进先出(返回键或finish()出栈)。

Activity的几种状态

Activity状态

说明

运行状态

处于返回栈栈顶,用户可见,能与用户交互。

暂停状态

不处于栈顶,可见;例如、弹出窗口页面后。

停止状态

不处于栈顶,不可见

销毁状态

从栈中移除。

Activity的生命周期

Activity各生命周期方法回调时期与页面状态

生命周期方法

Activity页面状态

方法体内容

onCreate

不可见状态

第一次创建后调用,设置布局、初始化组件、注册需要的广播接收者和数据绑定。

onStart

可见状态,此时不能与用户交互

部分资源(需要更新的)的加载,可以检测设置数据对象是否为空等。

onResume

可见状态,当前界面可以进行交互,activity为栈顶

大部分核心功能在此方法中实现。

onPause

可见状态,此时activity正在停止

数据存储、动画停止、资源回收。

onStop

不可见状态,activity完全停止或完全被覆盖

资源释放操作,不做耗时操作。

onDestroy

Activity销毁

回收工作和最终资源释放

onRestart

Activity重新启动时(后台回到前台,新act返回旧act)

恢复数据操作。

可归结三个关键周期:

从onCreate到onDestroy(整个的生命周期)

从onStart开始到onStop结束(可见的生命周期)

从onResume开始到onPause结束(前台的生命周期)

常见操作中Activity生命周期回调流程

正常启动:onCreate() -> onStart() -> onResume()

正常退出:onPause() -> onStop() -> onDestroy()

横竖屏切换:onPause() -> onStop() -> onDestroy() -> onCreate() -> onStart() -> onResume()

解决方法:在AndroidManifest.xml中的<activity>

添加configChanges = “keyboardHidden|screenSize|orientation”

或添加screenOrientation = landscap此方式适合游戏类应用。

        <activityandroid:name=".MainActivity"android:exported="true"android:configChanges="keyboardHidden|screenSize|orientation"><!--   android:screenOrientation="landscape"--><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>

当A跳转到B,并按下返回键

A:onCreate -> onStart -> onResume ->onPause

B:onCreate -> onStart -> onResume

A:onStop

当按下返回键:

B:onPause

A:onRestart -> onStart -> onResume

B:onStop -> onDestory

按下Home键

onPause -> onStop

从后台回来:

OnRestart -> onStart -> onResume

Activity的注册

Activity需要在AndroidManiFest.xml中进行配置完成注册。

        <activityandroid:name=".MainActivity"android:exported="true"android:configChanges="keyboardHidden|screenSize|orientation"><!--   android:screenOrientation="landscape"--><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>

Activity间的跳转方式

显示跳转:需要知道activity的类名。适合应用内跳转。

Intent intent = new Intent(this,SecondActivity.class);startActivity(intent);

隐式跳转:要知道activity的 意图过滤器中的action和Category或data属性。适合应用间的跳转。

      <activity android:name=".BActivity"android:exported="true"><intent-filter><action android:name="My_Action"/><category android:name="MyCategory"/><category android:name="android.intent.category.DEFAULT"/></intent-filter></activity>
    public void toBActivity(View view){Intent intent = new Intent();intent.setAction("My_Action");intent.addCategory("MyCategory");startActivity(intent);}

注:系统会默认为intent中添加“android.intent.category.DEFAULT”所以为能够正常采用隐式跳转必须设置category有DEFAUL。

Activity 的四种启动模式

在<activity>中的launchMode来配置

standard(标准)模式:也是Activity的默认的模式,每次启动Activity都会有新的Activity实例进入栈顶,不管是栈顶还是栈内,有多少个同样的实例都会被创建。

singleTop(栈顶复用)模式:和standard一样 ,不过Activity实例在栈顶就不再创建,复用已有。

singleTask(栈内复用)模式:如果有Activity实例在栈顶就不会创建新的实例,复用已有的Activity即可;若在实例之上有其他Activity的实例则弹出其他的Activity实例,复用已有Activity。

singleInstance(单实例)模式:保证系统无论从哪个Task启动Activity都只会创建一个Activity实例,并将它加入新的Task栈顶 也就是说被该实例启动的其他Activity会自动运行于另一个Task中。已存在无论在那个栈都会到前台显示。 singleInstance的Activity位于栈顶,因为它所在的Task仅有它一个Activity。

四种启动模式的应用场景

standard模式:默认启动模式,大部分页面都是这些模式。

singleTop模式:用于通知栏,推送消息页面。

singleTask模式:应用首页,首页只有一个。

singleInstance模式:独立栈操作的应用,启动与程序分离情况,闹钟的提醒、打开其他应用。

问题思考

若跳转到一个是窗口的Activity,生命周期回调情况?

A:onPuse

B:onCreate -> onStart -> onResume

点击返回:A: onResume

解释:因为A页面还是可见的,不会调用onStop。

锁屏/解锁生命周期回调情况?

锁屏:onPause -> onStop

解锁:onRestart -> onStart -> onResume

内存不足时候杀死Activity的顺序?

后台(用户不可见) > 可见不能操作 > 前台

在隐式跳转中,若目标activity没有在意图过滤中没加category会发生什么?

例子:

<activity android:name=".BActivity"

android:exported="true">

<intent-filter>

<action android:name="My_Action"/>

</intent-filter>

</activity>

Intent intent = new Intent();

intent.setAction("My_Action");

startActivity(intent)

在隐式跳转中能匹配到两个Activity是否能够编译通过?运行结果什么样?

可以编译通过,会让你选择进入哪个页面。

Activity结束和进程结束方式有哪些?其他activity结束进程会发生什么?

Activity结束自己finish();

结束整个进程android.os.Process.killProcess(android.os.Process.myPid());System.exit(0);

注:程序主页面结束进程会退出程序,跳转到其他页面结束进程,结束后会自己启动。

Service

是什么?

可长期运行在后台没有界面的组件。可由其它组件启动,组件通过绑定可以与其交互。

Service类型

前台服务

执行用户能注意到的操作。音乐播放,用户可以通过通知栏知道当前播放的内容。

后台服务

执行用户不会注意到的操作。上传、定时关闭

绑定服务

绑定后可以与绑定组件进行交互。

Service的注册

与Activity类似需要在AndroidManifest.xml中进行注册。

<service android:name=".services.FirstService" />

还能写其他属性android:permission是权限声明,android:process设置具体的进程名称。

Service生命周期

两种绑定方式及其生命周期

        startService方式:onCreate -> onStartCommad -> onDestory(想要启动一个后台服务进行某项任务)

        bindService方式:onCreate -> onBind -> onUnbin -> onDestroy(需要与服务进行通信)

通过bind方式开启的服务会与调用者的生命周期进行绑定,并能进行通信,单启动时,调用者销毁服务也会销毁,start开启的不会销毁但不会通信。当所有的客户端都和service解除绑定后,系统会销毁service。(除非service也被startService()方法开启)

        混合开启服务方式:onCreate-> onStartCommad -> onBind (想长期运行并通信,调用者结束服务不结束)

开启服务,能够确保服务长期运行

绑定服务,能够通信(只把Service的IBinder对象传递给Activity,不会绑定两个对象的生命周期)

退出activity,要解绑服务释放资源

Service一般在主线程中,注意不要进行耗时操作。

重复调用startService或者bindService

重复调用startService会重复执行onStartCommand,onCreate只会执行一次。

重复调用bindService时只回调一次onBind,之后只会直接把IBinder对象传递给后来的客户。

如果Service已经由某个客户端通过StartService()启动,接下来由其他客户端 再调用bindService()绑定到该Service后调用unbindService()解除绑定最后在 调用bindService()绑定到Service的话,此时所触发的生命周期方法如下:

onCreate( )->onStartCommand( )->onBind( )->onUnbind( )->onRebind( )

问题思考

Service与Thread线程的区别?

两者没有太大关系,Thread是线程,程序执行的最小单元,分配CPU的最小单元,可以运行耗时操作。Service是安卓的组件,运行在主进程的主线程上。不同的Activity中无法对同一线程进行控制。

只要回调了onStartCommad服务就会长期运行,尽管调用者销毁。(没有服务内容)65s后会自动销毁。(Android12)

Service应用场景

音乐播放、下载、上传大文件、定时关闭应用的功能。

Service里可以弹Toast吗?为什么?

可以,一它在主线程,可以刷新UI,二是context的子类有上下文。有些时候就可以通过toast告诉用户发生了什么事。

一个服务可以被多个客户端(Activity)绑定吗?

可以,但只有第一个组件绑定时才调用onBind(),其它的只是传递个IBinder对象给绑定组件以便通信。

为什么需要前台服务?

若服务在后台的运行,当内存不足时可能会优先对其进行回收,为了能够保持服务长期工作可置为前台服务。

Broadcast

什么是?

广播是程序组件之间的传输消息的机制,广播的内容是一个intent,在其中携带数据,他没有用户界面。

同一APP中不同组件传输,不同APP组件间传输消息。

默认情况下广播接收者运行在UI线程中。

广播的类型

标准广播:异步执行,发出后接收者几乎同一时刻收到广播。

有序广播:同步执行,同一时间只有一个接收者能收到,这个接收者可以选则停止,执行完逻辑后继续传递,还可修改广播内容。

粘性广播:粘性广播发送后在没有找到任何接收方的情况下会一直等待,接收者重建会接收到广播。(确保重要的状态改变后的信息被持久保存,并且能随时广播给新的广播接收器)

系统广播:有系统程序发出的广播,是标准广播。主要涉及到手机的基本操作

action                                         触发时机

android.net.conn.CONNECTIVITY_CHANGE       网络连接发生变化

android.intent.action.SCREEN_ON                屏幕点亮

android.intent.action.SCREEN_OFF               屏幕熄灭

android.intent.action.BATTERY_LOW           电量低,会弹出电量低提示框

android.intent.action.BATTERY_OKAY          电量恢复了

android.intent.action.BOOT_COMPLETED        设备启动完毕

android.intent.action.DEVICE_STORAGE_LOW   存储空间过低

android.intent.action.DEVICE_STORAGE_OK      存储空间恢复

android.intent.action.PACKAGE_ADDED          安装了新的应用

android.net.wifi.STATE_CHANGE                 WiFi 连接状态发生变化

android.net.wifi.WIFI_STATE_CHANGED       WiFi 状态变为启用/关闭/正在启动/正在关闭/未知

android.intent.action.BATTERY_CHANGED      电池电量发生变化

android.intent.action.INPUT_METHOD_CHANGED      系统输入法发生变化

android.intent.action.ACTION_POWER_CONNECTED 外部电源连接

android.intent.action.ACTION_POWER_DISCONNECTED    外部电源断开连接

android.intent.action.DREAMING_STARTED             系统开始休眠

android.intent.action.DREAMING_STOPPED             系统停止休眠

android.intent.action.WALLPAPER_CHANGED         壁纸发生变化

android.intent.action.HEADSET_PLUG               插入耳机

android.intent.action.MEDIA_UNMOUNTED             卸载外部介质

android.intent.action.MEDIA_MOUNTED               挂载外部介质

    //发送标准广播private void sendSecondBroadcast() {Intent intent = new Intent();intent.setAction("com.archermind.mybroadcast.UNORDER_BROADCAST");sendBroadcast(intent);}
    //发送有序广播public void sendOrderBroadcast(View view){Intent intent = new Intent();intent.setAction("com.archermind.mybroadcast.ORDER_BROADCAST");Bundle bundle = new Bundle();bundle.putInt("money", 1000 * 500);sendOrderedBroadcast(intent, "com.archermind.mybroadcast.MY_PERMISSION",null,null,1,"1000",bundle);}

广播接收者注册

动态注册:IntentFilter添加Action,调用registerReceiver,不用时记得取消注册。Activity启动后才能注册。

静态注册:在AndroidManiFest.xml中采用<recevier>标签配置注册。应用不启动就可以接收广播。

注:广播发送给静态注册的接收者时需要为intent设置component包名和路径;发送给动态注册的不需要设置,设置反而接收不到。

//向静态注册接收者发送广播Intent intent = new Intent();intent.setAction("com.archermind.mybroadcast.SEND_BROADCAST_ON_CLICK");intent.setComponent(new ComponentName(getPackageName(),"com.archermind.mybroadcast.SendBroadcastActivity$InnerReceiver"));intent.putExtra("Content","点击发送广播");sendBroadcast(intent);

//向静态注册接收者发送广播

Intent intent = new Intent();

intent.setAction("com.archermind.mybroadcast.SEND_BROADCAST_ON_CLICK");

intent.setComponent(new ComponentName(getPackageName(),"com.archermind.mybroadcast.SendBroadcastActivity$InnerReceiver"));

intent.putExtra("Content","点击发送广播");

sendBroadcast(intent);

广播中的权限(广播安全性问题的解决)

谁有权接收我的广播:广播发送者需要在AndroidManifest.xml中设置<permission android:name="com.archermind.mybroadcast.MY_PERMISSION"/>

谁有权给我发送广播:静态注册中的<receiver>加上permission属性。

//广播发送者的AndroidManifest.xml中

<permission android:name="com.archermind.mybroadcast.MY_PERMISSION"/>

//广播的发送

sendBroadcast(intent,"com.archermind.mybroadcast.MY_PERMISSION");

sendOrderedBroadcast(intent, "com.archermind.mybroadcast.MY_PERMISSION",null,null,1,"1000",bundle);

//谁有权给我发广播,动态广播接收者的注册

registerReceiver(receiveBroadCast, intentfilter, "com.archermind.mybroadcast.MY_PERMISSION" ,null);

//谁有权给我发广播,静态广播接收者的注册

<receiver android:name=".BootCompleteReceiver"

android:exported="true"

android:permission="com.archermind.mybroadcast.MY_PERMISSION">

<intent-filter>

<action android:name="android.intent.action.BOOT_COMPLETED"/>

</intent-filter>

</receiver>

问题思考

BroadCastReceiver中有那些应用场景?

APP内部消息通信。

不同APP之间的消息通信。

接收系统发出的设备信息。

广播优先级对无序广播生效吗?

优先级对无序广播生效

动态注册谁的优先级更高?

一自己设置优先级,二谁先注册谁高。

如何判断当前广播接收者收到的广播是有序还是无序?

在onReceive中调用isOrderedBroadcast()

BroadcastReceiver中为什么不能执行耗时操作?

  • BroadcastReceiver一般处于主线程中,时间超过10s会报ANR错误。
  • BroadcastReceiver启动较快,若进程中只有一个接收者并开了耗时的子线程,系统会认为是空进程,系统会优先杀死。

前台广播后台广播?

前台广播对应前台队列,后台广播对应后台队列。可以通过设置Intent.FLAG_RECEIVER_FOREGROUND属性来将广播定义为前台广播,如果未定义,默认使用后台广播。前台广播超时时间是10s,后台是60s。

ContentProvider内容提供者

什么是?

实现数据共享的重要组件,自身和其他应用所存储数据的访问,并提供与其他应用共享数据的方法。

使用场景:

访问其他应用中的现有的内容提供者;在应用中创建新的内容提供程序,从而实现与其他应用的内容共享。

ContentProvider的注册

需要在AndroidManifest.xml中进行注册

  <providerandroid:exported="true"android:authorities="com.archermind.mycontentprovider"android:name=".provider.StudentScoreProvider"/>

ContentProvider执行过程

ContentProvider实现数据共享

当一个应用程序要把自己的数据暴露给其他程序时,通过ContentProvider来实现。

其他应用可以通过ContenrResolver来操作ContentProvider暴露的数据。

定义自己的ContentProvider类,该类需要继承Android系统提供的ContentProvider基类。

在Manifest.xml 文件中注册ContentProvider,(四大组件的使用都需要在Manifest文件中注册) 注册时需要绑定一个URL

调用Activity的ContentResolver获取ContentResolver对象

调用ContentResolver的insert(),delete(),update(),query()进行增删改查。

一般来说,ContentProvider是单例模式,也就是说,当多个应用程序通过ContentResolver来操作ContentProvider提供的数据时,ContentResolver调用的数据操作将会委托给同一个ContentResolver。

ContentProvider、ContentResolver之间的关系?

ContentProvider内容提供者, 用于对外提供数据。

ContentResolver内容解析者, 用于获取内容提供者提供的数据。

一个应用可以实现ContentProvider来提供给别的应用操作,通过ContentResolver来操作别的应用数据。

内容URI模式

为表使用的内容 URI 模式是 content://<authority>/<path>

为单个行使用的内容 URI 模式则是 content://<authority>/<path>/<id>。

问题思考

ContentProvider和sql的实现上的有什么差别?

ContentProvider屏蔽了数据存储细节,使用者只需要关心操作数据的uri,它还可以实现不同app之间的共享。Sql只能增删改查本应用数据库。

多个进程同时调用一个ContentProvider的query获取数据,ContentProvider是怎么反应的?

多进程访问ContentProvider请求会按队列的形式进入ContentProvider,在一个进程中线程是互斥的。

四大组件小结

四大组件都是系统提供的,所以在写代码时都是要继承系统相应的类的。

生命周期方法都是系统管理的,尽量避免自己调用其系统方法。

四大组件都是要注册的,其中Broadcast能用动态注册,其他的都在AndroidManifest.xml中注册的。

其中Activity是有用户界面,其他组件没有。

它们一般都运行在主线程中,所以尽量不把耗时操作写在其中,在主线程中可以修改UI。

ANR报错

Input dispatching timed out

输入时间分发超过5s,包括按键和触屏事件

Broadcast of Intent

前台广播需要在10s,后台广播需要在60s

executing service

前台服务需要在20s,后台则需要在200s

ContentProvider

publish执行未在10s内完成?

Service.startForeground()

应用调用startForegroundService,然后5s内未调用startForeground出现ANR或者Crash

Fragment

什么是?

相当于自定义的组件(一个小的Activity),在需要Fragment的Activity的.xml中写上<fragment>就会显示其内容。有自己的生命周期并依赖于Activity,Activity销毁fragment也销毁。

Fragment的生命周期

Fragment的创建方式

静态加载Fragment

动态加载Fragment

注:容器是布局,组件的话只能添加或替换一次。

FragmentManager对象(管理fragment)

findFragmentById()

获取指定的fragment

popBackStack()

弹出后台Fragment

addToBackStack()

加入栈

FragmentTransaction对象(事务管理)

add()

向Activity中添加一个Fragment

remove()

移除一个已存在的Fragment

replace()

替换一个已被添加进视图容器的Fragment

show()hide()

展示一个fragment

Fragment传递数据给Activity(F的数据显示到A的UI中)(回调接口方式)

三种调用方式

​​​​

同步调用:一种阻塞式调用,A的方法中调用B的方法,需要等待B返回结果,A才能继续进行。

异步调用:类似消息和事件处理机制,A通知B后,然后各自运行。

回调:双向的调用模式,A要调用B(A需要F的数据),B在执行完又要调用A。

//在fragment中创建发送信息接口

public class Fragment1 extends Fragment {

oneSendValue mMySendValue;

… …

public interface oneSendValue{

void oneSend(String s);

}

… …

}

//在Activity中实现这个接口

public class MainActivity extends AppCompatActivity implements Fragment1.oneSendValue {

……

@Override

public void oneSend(String s) {

textView.setText(s);

}

……

}

//在fragment调用实现的接口函数

public class Fragment1 extends Fragment {

oneSendValue mMySendValue;

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

……

Button button=view.findViewById(R.id.button_my);

button.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

String s=editText.getText().toString();

mMySendValue.oneSend(s);

}

});

return view;

}

……

}

问题思考

动态加载成功后进行横竖屏切换Fragment生命周期函数?

走销毁再创建的生命周期

Fragment堆积怎么解决?

堆积出现出原因:每次加载时都是new的新的Fragment对象,动态加载到Activity中。

加载语句为:

getFragmentManager().beginTransaction().add(R.id.frameLayout1,new BlankFragment1()).commit();

解决方法:将Fragment抽出为成员变量,再加载前判空,若不为空对象show()出来。

if(blankFragment2 == null){

blankFragment2 = new BlankFragment2();

fragmentTransaction.add(R.id.frameLayout2,blankFragment2).commit();

} else {

fragmentTransaction.show(blankFragment2);

}

多线程

Android的应用与用户的交互大多都是在主线程中完成(UI显示、界面交互),为了用户体验,耗时操作就不能在主线程中(Android有个ANR报错),所以耗时的操作就要在线程中进行。

Thread类

//两个继承Thread的类

private class MyThread1 extends Thread{

private int ticket = 3;

private String name ;

public MyThread1(String name){

this.name = name;

}

public void run(){

while(ticket > 0){

ticket--;

System.out.println(name + "卖掉了1张票,剩余票数为:"+ticket);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

private class MyThread2 extends Thread{……}

//调用的地方

public void startSellTicket1(View view) {

MyThread1 myThread1 = new MyThread1("张三");

MyThread2 myThread2 = new MyThread2("李四");

myThread1.start();

myThread2.start();

}

运行结果

是Java中实现多线程的具体类,封装了线程操作。

线程对象:运行线程的实体,线程对象是控制线程行为的唯一手段。

特点:实现简单 只需要继承Thread类和复写run()方法;局限性大(Java是单继承)、不适合资源共享(一个线程=一个对象,相对独立)、消耗资源(一个线程=一个耗时任务,多此创建多次销毁)。

注:Tread线程不能操作UI。

Runnable类

//实现Runnable接口的类

private class MyThread3 implements Runnable{

private int ticket = 9;

@Override

public void run() {

while(ticket > 0){

ticket--;

System.out.println(Thread.currentThread().getName() + "卖掉了1张票,剩余票数为:" + ticket);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

public void startSellTicket2(View view) {

MyThread3 myThread3 = new MyThread3();

new Thread(myThread3,"张三").start();

new Thread(myThread3,"李四").start();

}

运行结果

它是一个多线程相关的抽象接口,仅定义了一个run()方法。

特点:适合资源共享(Runnable的代码可被多个先线程共享,适合多个线程处理同一资源)灵活(一个类可以实现多个接口)。

Thread类和Runnable的区别?

继承和接口的区别

class Thread implements Runnable{}

Thread和Runnable的实质是继承关系,没有可比性。无论使用Runnable还是Thread,都会new Thread,然后执行run方法。用法上,如果有复杂的线程操作需求,那就选择继承Thread,如果只是简单的执行一个任务,那就实现runnable

AsyncTask

是什么?

一个Android封装好的轻量级异步类。抽象类。

AsyncTask相关执行流程

注:Task的实例必须在主线程中创建;execute方法必须在主线程中调用;不要手动调用回调方法。一个Task实例只能执行一次,多次调用会有异常。

AsyncTask对象调用execute方法(可以传一个或多个参数)中调用onPreExecute(),然后是doInBackground(),在其中可以调用publishProgress(),doInBackground()的结果可以给onPostExecute(),在doBackground方法中,每次调用publishProgress方法都会触发onProgressUpdate()方法。

Handler

什么是?

Android系统中线程间传递消息的一种机制,线程间通信。(异步线程与主线程通信一般都有Handler)

Handler的引入

因为Android只允许UI线程中修改UI组件,Handler(发送与处理数据)可以解决周期性修改UI组件的属性。

Handler的执行流程

Looper

每个线程只能够有一个Looper,管理MessageQueue,不断地从中取出Message分发给对应的Handler处理!

Message对象

Message对象是封装了需要传递的数据给Handler处理。

Message.what:标识一个Message对象。

Message.obj:存储任意类型的Object对象。

线程池

频繁地为每一个任务创建一个线程,缺乏统一管理,降低性能,并且容易出现问题;线程池能对多线程进行同一管理,避免资源竞争中出现的问题;对线程进行复用;有完整的api操作方便。

线程池的执行过程

问题思考

Handler引起的内存泄露问题?

当使用内部类(包括匿名类)来创建Handler的时候(内部类持有外部引用),Handler对象会隐式地持有Activity的引用。

在请求网络过程中关闭了Activity,因为此时Handler又持有Activity的引用,就导致该Activity无法被收回,直至网络请求结束。

解决方法:使用弱引用。

一个线程有几个Handler?

可以有多个。

一个线程有几个Looper?如何保证?

一个。Looper的构造只能通过Prepare()方法(同时会初始化一个消息队列),当调用后ThreadLocal中的get()方法检查ThreadLocalMap中是否已经set过Looper。

当Activity重新创建时,(非静态内部类)AsyncTask的Activity的引用无效,怎么处理?

在Activity恢复时的对应方法重启 任务线程。

进程间通信

进程间通信方式:(file、内存共享)Binder机制,Bundle,Socket,AIDL,contentProvider

进程

进程是运行起来的程序,被加载到内存,进程独立运行,数据互不干扰。

前台进程:正在交互的进程

可见进程:可见不可操作

服务进程:不可见、后台、正在忙碌

后台进程:在后台,不做事

空进程:缓存作用

Binder

是一种Android中实现跨进程通信的方式,是一种虚拟的的物理设备驱动。

普通进程间通信和采用Binder机制进程间通信。

普通进程间通信

Binder跨进程通信机制

ServiceManager进程 管理Service注册与查询,Binder驱动一种虚拟驱动(传递进程间的数据:通过内存映射;实现线程控制:采用Binder的线程池)。

Bundle

用于消息传递,以键值对的形式保存数据,可以传递基本数据类型,也可传递引用类型(要实现Serializable或Parcelable的接口)。

结合Intent对象实现传递。

Socket

套接字,来描述IP地址和端口,是通信的句柄,通信双方通过Socket对象获得通信信息。

问题思考

服务进程后台进程区别?

调用startService方法启动的Service进程组件,没有与Activity绑定;不可见Activity,调用了onStop没有调用onDestroy

Android基础学习整理知识点相关推荐

  1. java基础学习整理(一)

    java基础学习整理(一) lesson1: D0s命令: 1.回到根目录,>cd \ 2.复制命令行下的内容,右击标记所要复制的内容,这样就已经复制好了,右击粘贴就可以了. 3.查看,设置环境 ...

  2. Android基础---学习历程【上课用到的资源---学期!汇总!整理】【课本源码、课后习题答案、上课课件与录播】

    专业课 名:Android开发基础A      2020年 上半年[大二下学期]学的. 目   录 推荐博客 学习帮助文档(必看) 课本(Android 移动开发基础 案例教程) 课本源码and课后习 ...

  3. pandas删除某列有空值的行_Python-零基础学习Pandas知识点整理(2)

    DataFrame数据的清洗--预处理操作 import pandas as pd import numpy as np #DataFrame数据框行或列的删除 #df.drop(labels=Non ...

  4. Android基础学习笔记13:安卓触摸事件触摸按键

    学习目标 了解安卓触摸动作 熟悉触摸监听器与方法 掌握单点触摸与多点触摸 在Android系统中,触摸是用户最常用,最基础的交互方式,只有弄通触摸事件在系统中的传递处理机制才能更好地增强用户的交互体验 ...

  5. Android基础学习第二篇—Activity

    写在前面的话: 1. 最近在自学Android,也是边看书边写一些Demo,由于知识点越来越多,脑子越来越记不清楚,所以打算写成读书笔记,供以后查看,也算是把自己学到所理解的东西写出来,献丑,如有不对 ...

  6. android基础学习之相机拍照部分

    在学习这个模块之前必须要对android有关于相机拍照的API有所了解  , 这个模块的API有两部分  一部分就是Camera 还有一部分 是Camera2 好像androidX包里面还有一个Cam ...

  7. Android 基础资料整理.

    #控件属性 1. TextView的属性 属性设置 值 android:id="" 控件的id android:layout_width="" 控件的宽度 wa ...

  8. android应用开发---(第1章)android基础学习之六大Layout布局

    Android中任何可视化的控件都是从android.veiw.View继承而来的,系统提供了两种方法来设置视图:第一种也是我们最常用的的使用XML文件来配置View的相关属性,然后在程序启动时系统根 ...

  9. Android基础学习笔记14:安卓手势编程

    学习目标 能理解手势操作原理 能利用手势操作实现切换功能 现代智能手机都支持触屏手势操作,可以方便地实现多种功能,最常见的是通过上下左右滑动手势实现切换功能. 一安卓手势操作原理 在安卓系统中,每一次 ...

  10. android基础学习

    一.创建应用程序和Activity Manifest.xml -->包含 Acitity.Service.Content Provider 和 Broadcast Receiver 节点,并使用 ...

最新文章

  1. Hadoop核心机制详细解析
  2. [Swift]LeetCode513. 找树左下角的值 | Find Bottom Left Tree Value
  3. 概率统计概念复习:MAPMLE
  4. mysql left day 7_day7-mysql函数
  5. mysql十分钟分组_MYSQL每隔10分钟进行分组统计的实现方法
  6. iOS 设置系统音量和监听系统音量变化
  7. 利用Hook技术实现键盘监控
  8. 今天成功的将一个对1,000,000条记录的查询从30'提升到1'以下,庆祝一下
  9. Codeforces 494D Birthday 树形dp (看题解)
  10. 新版ubuntu中打开终端的方法和安装ssh 的方法
  11. 日历c语言程序,一个完整的日历程序(含有农历)
  12. 修饰类方法(静态方法)
  13. USB及手机平板设备插拔响应解决方案
  14. java中map类型_Java中Map类型遍历的两种方式对比
  15. java自动签到_原来实现钉钉自动签到如此简单,每天准时上下班不是梦
  16. 100个python算法超详细讲解:掷骰子
  17. 代码的坏味道之十七 :Inappropriate Intimacy(狎昵关系)
  18. PMI2016大会最全资料集合
  19. 机场生产运行数据统计指标-第一篇-总述
  20. 【react】react18的学习(三)--hooks组件

热门文章

  1. 给宝宝的固态硬盘装机教程
  2. 数据库系统概论第五版(第 5 章 数据库完整性)笔记
  3. alisql安装教程
  4. dnf服务器运行库,吃鸡需要什么运行库 | 手游网游页游攻略大全
  5. J1939广播DM1报文
  6. wsdl2java 工具_apache CXF wsdl2java工具的使用
  7. ojdbc14.jar 和mysql_Oracle数据库的驱动包ojdbc*.jar之间的差别
  8. 2022年 MathorCup 思路分享
  9. 【_ 記 】topjui 多文件上传 (代码)
  10. NOIP2017普及组复赛 解题分析