我的应用程序上有一个启动页面,我想要做的是启动后台任务以开始下载内容,以便在用户需要时准备就绪。
例如,本周的图片或其他东西。
启动画面启动(启动后台任务)
启动画面完成(后台任务仍然有效)
主屏幕启动(临时“加载”占位符)
用户导航到另一个活动
下载完成
用户返回主屏幕,该屏幕更新为周的图片
现在我知道异步任务,但我听说异步任务在finish()
被取消,我也听说它们没有被取消。
这种任务,后台加载最好在服务中处理吗? 任何人都可以向我提供有关在后台加载此类内容的教程吗?
修改
人们提到UI工作应该在UI中,非UI在非UI中。我考虑过处理程序,但是当当前活动不活动时,监听器是否有效?
让我说我在main中启动一个处理程序,然后切换页面。当我回来时,我很确定主UI不会更新,因为在我查看另一个页面时,监听器没有触发。
我假设我必须创建一个仅用于存储变量或类的东西。服务完成后,它会将“pic_of_week_loaded”设置为true,当主要重新加载时,它会检查此var。我该怎么做呢?
答案 0 :(得分:2)
您可以从Application
类扩展,在其中创建一个基本上从Internet下载内容的线程(或AsyncTask)。完成后,您可以通知主屏幕活动,将内容显示在占位符中。
答案 1 :(得分:1)
考虑使用IntentService来完成你的后台工作,这样你就不会与活动生命周期保持联系。
编辑:根据评论。
使用自己的应用程序对象非常简单。只需像这样创建它:
final public class MyApplication extends Application {
....
}
然后将您的Manifest更新为:
<application
android:name=".MyApplication"
...
理论上就是这样。您现在可以在那里添加自己的方法,包括。异步任务操作。您只需MyApplication app = (MyApplication)getApplicationContext();
即可处理应用程序对象,然后执行app.XXX()
;但是有一些重要的注意事项:如果您想在ApplicationObject中使用AsyncTask,请注意Android Bug #20915。根据讨论,解决方法是在onCreate()
:
public void onCreate() {
// Workaround for android bug #20915
// http://code.google.com/p/android/issues/detail?id=20915
try {
Class.forName("android.os.AsyncTask");
} catch (Exception e) {
e.printStackTrace();
}
super.onCreate();
...
答案 2 :(得分:1)
另一种选择是使用Android Asynchronous Http Client
我会在活动中执行此操作,但请确保在显示活动时检查活动是否仍处于活动状态(确保尚未调用onDestroy)..
然后我会缓存结果,所以你不必再从网上加载它(将日期存储在文件名中,这样你就可以知道图片的日期,所以你知道缓存是否已经拥有最新的日期)
答案 3 :(得分:1)
我将尝试解释为什么(1)将全局状态保持在Application
sublcass中,(2)使用AsyncTask
对于这种情况都是不好的方法。
(1)如果应用程序不在前台并且此时应用程序中没有正在运行的服务,操作系统可能会终止您的应用程序进程。有关此内容的更多详情:How to declare global variables in Android?
(2)AsyncTask
比先看时更加诡异。 :)例如,如果((OS <1.6)||(OS> = 3.0))默认情况下所有任务都在同一个后台工作线程上运行。我的意思是当前Java进程的所有任务都在唯一的后台线程上执行。因此,在其他活动中下一个可能启动的任务将不得不等待直到第一个/ init完成。我认为这不是您想要获得的(如果用户从Home活动导航到其他一些活动,而另一个活动需要使用AsyncTask
加载一些数据,那么请确保您的第一个/ init任务已完成很快,因为它会阻止任何后续任务)。当然,如果第一个/ init任务的工作量不大,那么你可以不用担心这一点。有关AsyncTask
在此帖子中的工作原理的更多详细信息:Running multiple AsyncTasks at the same time -- not possible?
所以我的建议是使用IntentService
下载启动时所需的图像/日期。下载数据后,它会在SharedPreferences
中设置标志并发送广播。到目前为止,家庭活动可能处于3个州:
onResume()
,但尚未onPause()
)onPause()
,但尚未返回onResume
)当它处于活动状态时,它使用广播接收器来收听服务。当它暂停时,它会取消注册广播接收器,但是当它处于激活状态时,首先要做的是检查来自SharedPreferences
的标志。如果仍未设置标志,则注册广播接收器。
答案 4 :(得分:0)
1。好AsyncTask
已经引入到android中,以便为Painless Threading
提供它所知道的内容,但我不认为这就是这种情况....
2。现在,保持UI工作在UI线程上非常好,非UI工作在非UI线程上,并且成为规则从HoneyComb
Android版本的到来。
3。现在您想要在后台下载一些内容,这些内容不包含反映UI上的输出。然后我想你会查看java.util.concurrent中的CountDownLatch
类。
4. 此外,您始终可以在后台运行Non-UI thread
。
答案 5 :(得分:0)
我更喜欢将Threads
和Handlers
用于后台任务。线程将在后台执行某些操作,然后在任务完成时更新处理程序以更新UI。以下是一些示例代码:
Handler handler = new Handler() { //Declare this as a global variable to the class
@Override
public void handleMessage(Message msg) {
//display each item in a single line
if(msg.obj.equals("update subcat")){
subcategoryAdapter.notifyDataSetChanged();
}else if (msg.obj.equals("update products")){
productsAdapter.notifyDataSetChanged();
}else if (msg.obj.equals("update cat")){
categoryAdapter.notifyDataSetChanged();
}
}
};
这是你的后台任务:
Thread background = new Thread(new Runnable() {
@Override
public void run() {
getSubCategories(((Categories)searchResults.get(pos)).ID);
handler.sendMessage(handler.obtainMessage(pos, "update subcat"));
}
});
background.start();