后台HTTP任务

时间:2012-08-30 17:17:33

标签: java android service android-asynctask

我的应用程序上有一个启动页面,我想要做的是启动后台任务以开始下载内容,以便在用户需要时准备就绪。

例如,本周的图片或其他东西。

启动画面启动(启动后台任务)
启动画面完成(后台任务仍然有效)
主屏幕启动(临时“加载”占位符)
用户导航到另一个活动
下载完成
用户返回主屏幕,该屏幕更新为周的图片

现在我知道异步任务,但我听说异步任务在finish()被取消,我也听说它们没有被取消。

这种任务,后台加载最好在服务中处理吗? 任何人都可以向我提供有关在后台加载此类内容的教程吗?

修改
人们提到UI工作应该在UI中,非UI在非UI中。我考虑过处理程序,但是当当前活动不活动时,监听器是否有效?

让我说我在main中启动一个处理程序,然后切换页面。当我回来时,我很确定主UI不会更新,因为在我查看另一个页面时,监听器没有触发。

我假设我必须创建一个仅用于存储变量或类的东西。服务完成后,它会将“pic_of_week_loaded”设置为true,当主要重新加载时,它会检查此var。我该怎么做呢?

6 个答案:

答案 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)

我更喜欢将ThreadsHandlers用于后台任务。线程将在后台执行某些操作,然后在任务完成时更新处理程序以更新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();