0

我的应用程序上有一个启动页面,我想做的是启动一个后台任务来开始下载东西,以便在用户需要它们时准备好它们。

例如,一周的照片或其他东西。

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

现在我知道异步任务,但我听说异步任务会被取消,finish()而且我也听说它们不会被取消。

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

编辑:
人们提到 UI 工作应该在 UI 中,而非 UI 中的非 UI 中。我考虑过处理程序,但是当当前活动不活动时,侦听器是否工作?

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

我假设我必须创建一个类来存储变量或其他东西。服务完成后,它会将“pic_of_week_loaded”设置为 true,并且当主程序重新加载时,它会检查此 var。我该怎么办?

4

6 回答 6

2

您可以从类扩展Application,在其中创建一个线程(或 AsyncTask),基本上可以从 Internet 下载内容。完成后,您可以通知主屏幕活动以将内容显示到占位符中。

于 2012-08-30T17:24:50.947 回答
1

考虑使用IntentService来完成你的后台工作,这样你就不会被活动生命周期所束缚。

编辑:根据评论。

使用自己的应用程序对象非常简单。只需像这样创建它:

final public class MyApplication extends Application {
 ....
}

然后将您的清单更新为如下所示:

<application
    android:name=".MyApplication"
    ...

理论上就是这样。您现在可以在那里添加自己的方法,包括。异步任务操作。您可以使用 justMyApplication app = (MyApplication)getApplicationContext();然后 do来处理您的应用程序对象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();
  ...
于 2012-08-30T17:24:20.770 回答
1

另一种选择是使用Android Asynchronous Http Client

我只会在活动中执行此操作,但请确保在您显示活动时检查活动是否仍处于活动状态(确保尚未调用 onDestroy)..

然后我会缓存结果,这样你就不必从网络上再次加载它(将日期存储在文件名中,这样你就知道图片是哪个日期的,这样你就知道缓存是否已经保存了最新的)。

于 2012-08-30T17:44:13.343 回答
1

我将尝试解释为什么(1)在Applicationsublcas 中保持全局状态和(2)AsyncTask在这种情况下使用都是不好的方法。

(1) 如果应用程序不在前台并且当前应用程序中没有正在运行的服务,操作系统可能会终止您的应用程序进程。这篇文章中有更多详细信息:如何在 Android 中声明全局变量?

(2)AsyncTask比最初看起来更狡猾。:) 例如,如果 ((OS < 1.6) || (OS >= 3.0)) 默认情况下,所有任务都在同一个后台工作线程上运行。我的意思是当前 Java 进程的所有任务都在唯一的后台线程上执行。因此,其他活动中下一个可能开始的任务将不得不等到第一个/init 一个完成。我认为这不是您想要得到的(如果用户从 Home 活动导航到其他活动,并且另一个活动需要使用 加载一些数据AsyncTask,那么请确保您的第一个/init 任务快速完成,因为它会阻止任何后续任务)。当然,如果 first/init 任务的工作量不大,那么这点可以不用担心。关于这篇文章如何AsyncTask工作的更多细节:同时运行多个 AsyncTask —— 不可能吗?

所以我的建议是用来IntentService下载你在启动时需要的图像/日期。一旦下载数据,它就会设置标志SharedPreferences并发送广播。此时 Home 活动可能处于 3 种状态:

  • 活动(通过onResume(),但尚未onPause()
  • 暂停(通过onPause(),但尚未返回onResume
  • 毁坏

当它处于活动状态时,它使用广播接收器来收听服务。当它暂停时,它会注销广播接收器,但是当它处于活动状态时,它做的第一件事就是检查来自SharedPreferences. 如果 flag 仍未设置,则注册广播接收器。

于 2012-08-30T19:15:49.630 回答
0

1. WellAsyncTask被引入 android 以提供它所知道的Painless Threading,但我不认为这里是这种情况....

2.现在让UI工作在UI线程上总是好的,Non-UI工作在Non-UI线程上,这从Android版本的到来就成为了一个规则。HoneyComb

3.现在你想在后台下载一些东西,这不包括反映在 UI 上的输出。然后我想你看看CountDownLatchjava.util.concurrent中的Class。

4.否则,您可以随时Non-UI thread在后台运行。

于 2012-08-30T17:25:20.483 回答
0

我更喜欢将ThreadsandHandlers用于后台任务。线程会在后台执行一些操作,然后当任务完成时,更新处理程序以更新 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();
于 2012-08-30T17:27:54.613 回答