UI 线程上的片段 onStop 运行
Does fragment onStop run on UI thread
我在 ViewPager
中加载了一些片段,其中每个 "page" 都是从游标中的一行加载的。每个片段在设备上显示一个图像 (JPEG)。当用户关闭片段(即 swipe/page 更改、点击 back/up 或完全关闭应用程序)时,我想调用一个方法来打开 JPEG 文件进行写入并更新其元数据。实际工作最终由 Apache Commons Imaging 库处理。
我通过从每个片段的生命周期 onStop()
处理程序调用我的 saveToFile()
方法来实现这一点。 这是否意味着整个文件操作在 UI 线程上结束了 运行?我一定要为此设置一个 AsyncTask
吗?
假设由于某种原因突然写入文件(对于某些jpeg)需要很长时间,例如2分钟。那么会发生什么? UI 会在 page/fragment 处等待(冻结)再继续吗?或者这个过程(写入文件)会以某种方式进行 "in the background" 吗?或者这个过程会被杀死,在过程中短暂停止?
我目前的连接方式(onStop
调用 saveToFile()
,调用成像库然后更新文件)似乎可以正常工作。即使我结束应用程序,我仍然看到我的 Toast 文本弹出,说 "Writing to file..." 似乎,这个过程从未被打扰,我不能说我遇到任何 UI 滞后。
onStop() handler. Does this mean the entire file operation ends up
running on the UI thread? Should I definitely set up an AsyncTask for
this?
是
一个 AsyncTask 有几个部分:一个 doInBackground
方法,实际上 运行 在一个单独的线程上, onPostExecute
方法 运行 在UI 线程。
您还可以使用某种观察者模式,例如 EventBus 到 运行 异步和 post 结果到 UI.
Say the file write for some reason suddenly (for some jpeg) should
take a long time, eg 2 minutes. What would then happen? Would the UI
just wait (freeze)
应用程序将崩溃,因为 Android 将因 ANR(应用程序无响应)强行关闭它。
具体请参考官方文档:https://developer.android.com/training/articles/perf-anr.html
Android applications normally run entirely on a single thread by
default the "UI thread" or "main thread"). This means anything your
application is doing in the UI thread that takes a long time to
complete can trigger the ANR dialog because your application is not
giving itself a chance to handle the input event or intent broadcasts.
Therefore, any method that runs in the UI thread should do as little
work as possible on that thread. In particular, activities should do
as little as possible to set up in key life-cycle methods such as
onCreate() and onResume(). Potentially long running operations such as
network or database operations, or computationally expensive
calculations such as resizing bitmaps should be done in a worker
thread (or in the case of databases operations, via an asynchronous
request).
The most effective way to create a worker thread for longer operations
is with the AsyncTask class.
这是我推荐的。使用上面提到的 EventBus 并创建一个 BaseActivity
,它将通过触发 运行 异步事件自动为您保存数据 onClose()
。然后,在需要自动保存功能的所有地方扩展该基础 activity。
这就是我用一个使用 EventBus 的例子的意思。
public abstract class BaseActivity extends Activity{
@Override
protected void onResume(){
if(!EventBus.getDefault().isRegistered(this))
EventBus.getDefault().register(this);
super.onResume();
}
@Override
protected void onDestroy() {
if(EventBus.getDefault().isRegistered(this))
EventBus.getDefault().unregister(this);
super.onDestroy();
}
@Override
protected void onStop() {
super.onStop();
//We fire event and pass the current parent class that inherited this base.
EventBus.getDefault().post(new EventBusProcessMySaveData(this.getClass()));
}
}
//Your model class to use with EventBus
public final class EventBusProcessMySaveData{
private final Class className;
public EventBusProcessMySaveData(final Class className){
this.className = className;
}
public Class getClassName(){
return this.className;
}
}
public class MyMainActivity extends BaseActivity{
//Do you standard setup here onCreate() and such...
//Handle Event for Saving Operation, async.
//This will fire everytime theres an onClose() IN ANY activity that
//extends BaseActivity, but will only process if the class names match.
@Subscribe(threadMode = ThreadMode.ASYNC)
public void methodNameDoesNotReallyMatterHere(final EventBusProcessMySaveData model){
//We make sure this is the intended receiving end by comparing current class name
//with received class name.
if(model.getClassName().equals(this.getClass())){
//Do whatever you need to do that's CPUintensive here.
}
}
}
我在 ViewPager
中加载了一些片段,其中每个 "page" 都是从游标中的一行加载的。每个片段在设备上显示一个图像 (JPEG)。当用户关闭片段(即 swipe/page 更改、点击 back/up 或完全关闭应用程序)时,我想调用一个方法来打开 JPEG 文件进行写入并更新其元数据。实际工作最终由 Apache Commons Imaging 库处理。
我通过从每个片段的生命周期 onStop()
处理程序调用我的 saveToFile()
方法来实现这一点。 这是否意味着整个文件操作在 UI 线程上结束了 运行?我一定要为此设置一个 AsyncTask
吗?
假设由于某种原因突然写入文件(对于某些jpeg)需要很长时间,例如2分钟。那么会发生什么? UI 会在 page/fragment 处等待(冻结)再继续吗?或者这个过程(写入文件)会以某种方式进行 "in the background" 吗?或者这个过程会被杀死,在过程中短暂停止?
我目前的连接方式(onStop
调用 saveToFile()
,调用成像库然后更新文件)似乎可以正常工作。即使我结束应用程序,我仍然看到我的 Toast 文本弹出,说 "Writing to file..." 似乎,这个过程从未被打扰,我不能说我遇到任何 UI 滞后。
onStop() handler. Does this mean the entire file operation ends up running on the UI thread? Should I definitely set up an AsyncTask for this?
是
一个 AsyncTask 有几个部分:一个 doInBackground
方法,实际上 运行 在一个单独的线程上, onPostExecute
方法 运行 在UI 线程。
您还可以使用某种观察者模式,例如 EventBus 到 运行 异步和 post 结果到 UI.
Say the file write for some reason suddenly (for some jpeg) should take a long time, eg 2 minutes. What would then happen? Would the UI just wait (freeze)
应用程序将崩溃,因为 Android 将因 ANR(应用程序无响应)强行关闭它。
具体请参考官方文档:https://developer.android.com/training/articles/perf-anr.html
Android applications normally run entirely on a single thread by default the "UI thread" or "main thread"). This means anything your application is doing in the UI thread that takes a long time to complete can trigger the ANR dialog because your application is not giving itself a chance to handle the input event or intent broadcasts.
Therefore, any method that runs in the UI thread should do as little work as possible on that thread. In particular, activities should do as little as possible to set up in key life-cycle methods such as onCreate() and onResume(). Potentially long running operations such as network or database operations, or computationally expensive calculations such as resizing bitmaps should be done in a worker thread (or in the case of databases operations, via an asynchronous request).
The most effective way to create a worker thread for longer operations is with the AsyncTask class.
这是我推荐的。使用上面提到的 EventBus 并创建一个 BaseActivity
,它将通过触发 运行 异步事件自动为您保存数据 onClose()
。然后,在需要自动保存功能的所有地方扩展该基础 activity。
这就是我用一个使用 EventBus 的例子的意思。
public abstract class BaseActivity extends Activity{
@Override
protected void onResume(){
if(!EventBus.getDefault().isRegistered(this))
EventBus.getDefault().register(this);
super.onResume();
}
@Override
protected void onDestroy() {
if(EventBus.getDefault().isRegistered(this))
EventBus.getDefault().unregister(this);
super.onDestroy();
}
@Override
protected void onStop() {
super.onStop();
//We fire event and pass the current parent class that inherited this base.
EventBus.getDefault().post(new EventBusProcessMySaveData(this.getClass()));
}
}
//Your model class to use with EventBus
public final class EventBusProcessMySaveData{
private final Class className;
public EventBusProcessMySaveData(final Class className){
this.className = className;
}
public Class getClassName(){
return this.className;
}
}
public class MyMainActivity extends BaseActivity{
//Do you standard setup here onCreate() and such...
//Handle Event for Saving Operation, async.
//This will fire everytime theres an onClose() IN ANY activity that
//extends BaseActivity, but will only process if the class names match.
@Subscribe(threadMode = ThreadMode.ASYNC)
public void methodNameDoesNotReallyMatterHere(final EventBusProcessMySaveData model){
//We make sure this is the intended receiving end by comparing current class name
//with received class name.
if(model.getClassName().equals(this.getClass())){
//Do whatever you need to do that's CPUintensive here.
}
}
}