Android开发爱上Android

Android知识总结

2019-01-27  本文已影响6人  元创造力

1.打开一个App, 从主页跳转到其深层子页面,按HOME键回到桌面,再次打开,怎么才能使再次打开看到的是主页面?
(注:这个过程app并没有被回收销毁)

答:这个是通过配置主页Activity在Manifest里面的标签属性即可实现

 <activity android:name=".MainActivity"
    android:clearTaskOnLaunch="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
 </activity>

给主Activity添加属性android:clearTaskOnLaunch = "true"即可实现

2.一个Activity的启动模式是singleTop,如何实现像singleTask模式的启动效果,即如果这个Activity不在这个任务栈中,创建一个新的实例,如果在这个任务栈中,无论是否在栈顶,都复用之前的实例,不再重新创建了,如果不在栈顶,则,把它上面的Activity出栈,把此Activity置于栈顶? (注:不要改变这个Activity启动模式为singleTask的前提下)

答:在启动此Activity的时候,为intent添加一个FLAG为 Intent.FLAG_ACTIVITY_CLEAR_TOP 即可。

Intent i = new Intent(this,SecondActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);

下面是Android源码对 Intent.FLAG_ACTIVITY_CLEAR_TOP 的解释

 If set, and the activity being launched is already running in the
 current task, then instead of launching a new instance of that     
 activity,all of the other activities on top of it will be closed 
 and this Intent will be delivered to the (now on top) old 
 activity as a new Intent.

 For example, consider a task consisting of the activities: A, 
 B, C, D.If D calls startActivity() with an Intent that resolves to 
 the component of activity B, then C and D will be finished and 
 B receive the given Intent, resulting in the stack now being: A, 
 B.The currently running instance of activity B in the above 
 example willeither receive the new intent you are starting here 
 in it onNewIntent() method, or be itself finished and restarted with the
 new intent.  If it has declared its launch mode to be "multiple" 
(thedefault) and you have not set {@link#FLAG_ACTIVITY_SINGLE_TOP} 
 in the same intent, then it will be finished and re-created; for 
all other launch modes or if {@link#FLAG_ACTIVITY_SINGLE_TOP} is set
 then this Intent will be delivered to the current instance 
onNewIntent(). 

This launch mode can also be used to good effect in 
conjunction with{@link#FLAG_ACTIVITY_NEW_TASK}:
if used to start the root activity of a task, it will bring any 
currently running instance of that  task to the foreground, and 
then clear it to its root state.  This is especially useful, for 
example, when launching an activity 
 from the notification manager.

如果设置这个属性,并且这个activity已经在当前任务栈中运行,那么就不会再在这个任务栈中为这个activity创建一个新的实例,而是复用这个存在的实例,并且此Activity上面所有其他的activities都会被出栈,这个intent会被传递给这个被复用的activity实例。

例如:一个任务栈中有A、B、C、D四个activity,如果D通过包含此FLAG的Intent调起B,那么C、D将会被 关闭掉,B会接收到这个intent,此时任务栈中只有A、B两个activity了

在上面的例子中,这个正在运行的Activity B 将会通过onNewIntent()方法接收intent或者他自动关闭在重新启动 , 如果Activity B的启动模式是默认的,且设置的不是FLAG_ACTIVITY_SINGLE_TOP,那么ActivityB会自动销毁并且重启,如果设置的是其他启动模式或者是singleTop的话,Activity B将不会销毁重建,而是被复用,通过onNewIntent();接收传递过来的intent。

这个启动模式(Intent.FLAG_ACTIVITY_CLEAR_TOP)和(FLAG_ACTIVITY_NEW_TASK)一起使用将会起到很好的效果, 如果你想启动某个根Activity,那么它会把包含这个根Activity的任务栈放到前台运行,并且会把这个任务栈中的根 Activity之上的其他activies都出栈,把此根activity置于栈顶。这是非常有用的,例如通过通知管理器启动activity

3.如果连续多次启动某个IntentService,会为这个IntentService创建多个实例吗,IntentService里面的耗时操作是各自执行吗?

答:首先看一下IntentService的官方解释

IntentService is a base class for {@link Service}s that handle asynchronous
requests (expressed as {@link Intent}s) on demand. Clients send requests
through {@link android.content.Context#startService(Intent)} calls; the
service is started as needed, handles each Intent in turn using a worker
thread, and stops itself when it runs out of work.

This "work queue processor" pattern is commonly used to offload tasks
from an application's main thread. The IntentService class exists to
simplify this pattern and take care of the mechanics. To use it, extend
IntentService and implement {@link #onHandleIntent(Intent)}. IntentService
will receive the Intents, launch a worker thread, and stop the service as
appropriate.

All requests are handled on a single worker thread -- they may take as
long as necessary (and will not block the application's main loop), but
only one request will be processed at a time.

意思就是IntentService可以处理异步请求,客户端通过startService(Intent)发来请求,
IntentService相应的就会启动,每个intent都会通过一个工作线程处理,并且任务执行
完之后,会自动结束掉

这种工作队列处理器模式主要是用来处理主线程发来的卸载任务,IntentService的存在简化
这种模式并且它比较关注的是运行机制。可以通过继承IntentService并且实现onHandleIntent(Intent)
来使用它。IntentService收到Intent之后,会开启一个工作线程,并且会在何时的时间自动关闭。

所有的请求都会交给一个异步线程处理,每个任务都会花费掉他们所需要长的时间来处理,但是不会阻塞
主线程,但是每次只能处理一个任务。
复制代码
下面简单看一下IntentService的源码:

@Override
public void onCreate() {
    // TODO: It would be nice to have an option to hold a partial wakelock
    // during processing, and to have a static startService(Context, Intent)
    // method that would launch the service & hand off a wakelock.

    super.onCreate();
    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
    thread.start();

    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
 }

复制代码
首先IntentService的onCreate()方法创建了一个HandlerThread并且启动了它,并且把它持有的Looper给了
mServiceHandler,那么mServiceHandler处理的就是这个子线程里面的消息了 并且无论startService多少次,IntentServcie的onCreate()方法就执行一次,所以即便是有很多个任务,也只会
只有一个工作线程来处理。

@Override
public void onStart(@Nullable Intent intent, int startId) {
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

复制代码
再来看IntentService的onStart()方法,它得到了一个message对象,并且把intent存储在里面,通过
mServiceHandler发送了出去,那么这个message对象最终会被存储到子线程的Queue中去,然后再通过
子线程的Looper.loo()方法取出,给mServiceHandler.handleMessage(Message)处理,这样对Intent的处理
就从主线程转移到了子线程,并且每调用startService(Intent)一次,onStart()方法就执行一次,这样
接收到的Intent就会一次通过mServiceHandler发送到消息队列里面等待处理。

private final class ServiceHandler extends Handler {
    public ServiceHandler(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
        onHandleIntent((Intent)msg.obj);
        stopSelf(msg.arg1);
    }
}

@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);

复制代码
如上所说:最终Intent通过mServiceHandler的handleMessage(Message)方法传给了onHandleIntent(Intent)
来处理了,此时已经是在异步线程中了,如果有多个任务,都会存放到消息队列里面去,等待处理,但是始终只有
一个IntentServide实例,并且只有一个子线程来处理任务。

上一篇下一篇

猜你喜欢

热点阅读