我在ViewPager
中加载了一些片段,其中每个“页面”都从光标中的一行加载。每个片段在设备上显示图像(JPEG)。当用户解散片段时(即滑动/页面更改,回击/向上或完全关闭应用程序),我想调用一个方法打开JPEG文件进行写入并更新其元数据。实际工作最终由Apache Commons Imaging库处理。
我已经通过从每个片段的生命周期saveToFile()
处理程序调用我的onStop()
方法来实现这一点。 这是否意味着整个文件操作最终在UI线程上运行?我应该为此设置AsyncTask
吗?
由于某种原因突然(对于某些jpeg)说文件写入需要很长时间,例如2分钟。然后会发生什么? UI会在恢复之前等待(冻结)此页面/片段吗?或者进程(写入文件)会以某种方式“在后台”进行?或者这个过程是否会被杀死,中途停止?
我当前有线连接的方式(onStop
调用saveToFile()
,调用映像库然后更新文件)似乎应该正常工作。即使我结束了应用程序,我仍然看到我的Toast文本突然出现,说“写入文件......”看起来,这个过程从未受到干扰,我不能说我遇到任何UI延迟。
答案 0 :(得分:2)
onStop()处理程序。这是否意味着整个文件操作结束 在UI线程上运行?我应该确定为AsyncTask设置 此?
是强>
AsyncTask有几个部分:一个doInBackground
方法实际上在一个单独的线程上运行,而onPostExecute
方法在UI线程上运行。
您还可以使用某种观察者模式(例如EventBus)来运行异步并将结果发布到UI。
由于某种原因突然(对某些jpeg)说文件写应该 需要很长时间,例如2分钟。然后会发生什么? UI会吗? 等待(冻结)
应用程序将崩溃,因为Android会因ANR(应用程序无响应)而强制关闭它。
有关详细信息,请参阅官方文档:https://developer.android.com/training/articles/perf-anr.html
Android应用程序通常完全在单个线程上运行 默认为“UI线程”或“主线程”)。这意味着什么 应用程序正在UI线程中进行,需要很长时间 完成可以触发ANR对话框,因为您的应用程序不是 给自己一个处理输入事件或意图广播的机会。
因此,在UI线程中运行的任何方法都应该尽可能少 尽可能在该线程上工作。特别是,活动应该做 尽可能少地设置关键的生命周期方法,如 onCreate()和onResume()。可能长时间运行的操作如 网络或数据库操作,或计算上昂贵 调整位图大小等计算应该在worker中完成 线程(或者在数据库操作的情况下,通过异步 请求)。
为更长时间的操作创建工作线程的最有效方法 与AsyncTask类有关。
这是我推荐的。使用上面提到的EventBus并创建一个BaseActivity
,它将通过触发运行Async的事件自动为您onClose()
保存数据。然后,您可以在需要自动保存功能的所有位置扩展该基本活动。
这就是我对使用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.
}
}
}