2012-04-27 76 views
6

我有一个更新数据库操作,它有一个活动,它不断更新百分比,并在AsyncTask中运行。在后台工作时更新UI

doInBackground()我调用控制器来更新数据库并不断更新活动的百分比,但是,如果我按Home按钮或Back按钮,操作将被取消。你建议我做什么?

我试图在doInBackground()里面启动一个服务,所以它会在后台运行,但看起来它不工作。

我的代码如下所示:

public class UpdateDatabaseAsyncTask extends AsyncTask<Void, Integer, Integer> 
{ 
    @Override 
    public void onPreExecute() 
    { 
     mCustomProgressBar.startAnimation(); 
    } 

    @Override 
    public Integer doInBackground(Void... params) 
    { 
     return mController.updateDatabase(); 
    } 

    @Override 
    public void onPostExecute(Integer result) 
    { 
     mCustomProgressBar.stopAnimation(); 
     // finish the activity 
    } 

    @Override 
    public void onProgressUpdate(Integer... value) 
    { 
     updatePercentageValue(value[0]); 
    } 

    public void callPublishProgress(Integer value) 
    { 
     publishProgress(value); 
    } 
} 

而且控制器内我调用该方法callPublishProgress(value)传递当前的百分比值,所以它会在UI publishProgress(value)

我在调试,我按下了home/back按钮,它只是停止运行工作线程。


另一种解决办法我试过了,已开始服务在后台运行,无论用户按home /后退按钮或没有,所以我想和服务将使到执行的控制方法的调用工作,它会调用callPublishProgress(value)来更新UI上的百分比值。

然而,发生了什么事,代码达到doInBackground()并启动该服务,但它会立即转到onPostExecute(),它只是没等服务来完成(当然)。所以它给出了NullPointerException。我想在doInBackground()内设置一个循环,并在服务中设置了一个标志,所以当服务尚未完成时(我正在使用IntentService)它将离开此循环,但它无法工作。

我也想过使用定时器。但我不知道。

我正在阅读有关线程等文档的文章,并建议使用AsyncTask,就像我正在尝试做的一样。它也谈到了runOnUiThread(Runnable)

无论如何,我需要的是在后台进行操作(可能使用IntentService),所以无论用户按home键,它都会继续运行,但它必须更新UI的百分比,并且当用户离开屏幕并返回时,它会显示屏幕中更新的当前百分比值。

我的情况最好的解决方案是什么?

谢谢。

+0

请参阅SDK样品中的API演示,有其计数并通知服务的例子一个可以显示计数的前台活动。 – 2012-04-27 17:20:31

+0

这个样本的名称是什么? – rogcg 2012-04-27 17:26:28

+0

我不记得确切地说,它全部在sdk的samples /目录中的API demos应用程序中 - 构建完整的东西来运行它并查看菜单并浏览代码。其中很多其他有用的东西也值得了解。 – 2012-04-27 17:36:53

回答

3
public class MyServce extends Service{ 
public static final String BROADCAST_ACTION = "com.myapp"; 
Intent intent; 
private final Handler handler = new Handler(); 

@Override 
public void onCreate() 
{ 
    super.onCreate(); 
    intent = new Intent(BROADCAST_ACTION); 
} 

@Override 
    public void onStart(Intent intent, int startId) { 
     handler.removeCallbacks(sendUpdatesToUI); 
     handler.postDelayed(sendUpdatesToUI, 1000); // 1 second 

    } 
    private Runnable sendUpdatesToUI = new Runnable() { 
     public void run() { 
      DoYourWorking();   
      handler.postDelayed(this, 1000); // 1 seconds 
     } 

     private void DoYourWorking() { 
     ........ 
        ........ 
        intent.putExtra("key", progress); 
      sendBroadcast(intent); 

     } 
    }; 

@Override 
public IBinder onBind(Intent intent) { 
    // TODO Auto-generated method stub 
    return null; 
} 
@Override 
public void onDestroy() { 
    super.onDestroy(); 
    handler.removeCallbacks(sendUpdatesToUI);  

} 
在活动注册广播

我们服务

private BroadcastReceiver brodcast = new BroadcastReceiver() { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
       //intent.getWhatever 
     // update your progress 
     //progressbar.setProgress 
    } 

寄存器广播

registerReceiver(brodcast, new IntentFilter(MyService.BROADCAST_ACTION)); 
+0

工程就像一个魅力,但我不需要使用处理程序。我刚启动了IntentService,并从IntentService中调用了sendBroadcast(Intent)。非常感谢! – rogcg 2012-04-27 20:00:00

1

这对我有效。我在一个线程上启动了一个后台服务,该线程获取值并更新单例中的对象。

在视图控制器中,我启动了一个定时器,它通过从singleton中的对象获取数据来更新视图。

我在理解整个问题文本时遇到了一些问题,所以我不确定您是否尝试了这一点。但这是有效的。此外,该服务开始START_STICKY