我在Android上运行一个图书服务应用程序,用户将图书下载到他的设备上。图书文件是1mb及以上。 可以将异步任务视为此类操作的最佳实践。 是否有其他方法可以在后台线程中执行下载。 请建议。
答案 0 :(得分:1)
通常认为AsyncTask不适用于长时间运行的任务,但有时它是执行简单任务的简单方法(无论需要多长时间)。但问题是,一些开发人员以错误的方式执行它。
public class MainActivity extends Activity {
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// Somewhere the AsyncTask is started
public class MyAsyncTask extends AsyncTask<Void, Void, String> {
@Override protected String doInBackground(Void... params) {
// Do work
return result;
}
@Override protected void onPostExecute(String result) {
Log.d("MyAsyncTask", "Received result: " + result);
}
}
}
上面代码的问题是,当您在Activity中启动AsyncTask并旋转设备或发生任何配置更改时,Activity将被销毁并创建一个新实例。但AsyncTask不会死并继续运行直到它完成。
问题
1)由于活动很繁重,如果启动了几个AsyncTask,这可能会导致内存问题。 2)另一个问题是AsyncTask的结果可能会丢失,如果它打算对活动的状态采取行动。
所以我们需要解决两个问题
1)框架销毁时不应将活动保存在记忆中
2)AsyncTAsk的结果应该传递给当前的活动实例
要解决这些问题,我们需要 otto http://square.github.io/otto/
使用otto创建MyBus.java,我们必须将其用作单身人士
public class MyBus {
private static final Bus BUS = new Bus();
public static Bus getInstance() {
return BUS;
}
}
创建AsyncTaskResultEvent.java文件
public class AsyncTaskResultEvent {
private String result;
public AsyncTaskResultEvent(String result) {
this.result = result;
}
public String getResult() {
return result;
}
}
现在,在您的MainActivity中,执行AsyncTask
public class MyAsyncTask extends AsyncTask<Void, Void, String> {
@Override protected String doInBackground(Void... params) {
Random random = new Random();
final long sleep = random.nextInt(10);
try {
Thread.sleep(sleep * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Slept for " + sleep + " seconds";
}
@Override protected void onPostExecute(String result) {
MyBus.getInstance().post(new AsyncTaskResultEvent(result));
}
}
现在,启动AsyncTask的Activity将在稍后获得结果。
要修复内存泄漏问题,请在MainActivity中添加以下代码
@Override protected void onDestroy() {
MyBus.getInstance().unregister(this);
super.onDestroy();
}
@Subscribe public void onAsyncTaskResult(AsyncTaskResultEvent event) {
Toast.makeText(this, event.getResult(), Toast.LENGTH_LONG).show();
}
并将这行代码放在OnCreate方法中
MyBus.getInstance().register(this);
现在如果发生配置更改,我们将自动通知新Activity实例中的结果,因为它已注册到事件总线。