2013-03-18 80 views
66

我想要一些代码在后台连续运行。我不想在服务中做到这一点。有没有其他方法可行?如何在Android上的后台线程上运行代码?

我尝试过在我的Activity中调用Thread类,但我的Activity在后台保留了一段时间,然后停止。 Thread类也停止工作。

class testThread implements Runnable 
    { 
     @Override 
     public void run() 
     { 
      File file = new File(Environment.getExternalStorageDirectory(),"/BPCLTracker/gpsdata.txt"); 
      int i=0; 

     RandomAccessFile in = null; 

     try 
     { 
      in = new RandomAccessFile(file, "rw"); 


     } 
     catch (FileNotFoundException e) 
     { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     //String line =null; 
     while (true) 
     { 
      HttpEntity entity=null; 
      try 
      { 
       if (isInternetOn()) 
       { 
         while ((line = in.readLine()) != null) 
         { 

          HttpClient client = new DefaultHttpClient(); 
          String url = "some url"; 
          HttpPost request = new HttpPost(url); 
          StringEntity se = new StringEntity(line); 
          se.setContentEncoding("UTF-8"); 
          se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json")); 
          entity = se; 
          request.setEntity(entity); 
          HttpResponse response = client.execute(request); 
          entity = response.getEntity(); 
          i++; 
         } 
         if((line = in.readLine()) == null && entity!=null) 
         { 
          file.delete(); 
          testThread t = new testThread(); 
          Thread t1 = new Thread(t); 
          t1.start(); 
         } 


       }// end of if 
       else 
       { 
        Thread.sleep(60000); 

       } // end of else 
      }// end of try 
      catch (NullPointerException e1) 
      { 
       e1.printStackTrace(); 
      } 
      catch (InterruptedException e2) 
      { 
       e2.printStackTrace(); 
      } 
      catch (IOException e1) 
      { 
       // TODO Auto-generated catch block 
       e1.printStackTrace(); 
      } 
     }// end of while 
    }// end of run 
+1

嗨。你可以请张贴一些代码作为你尝试过的例子吗?在后台线程上运行代码有不同的方法,但是您必须记住,如果您访问的是任何UI组件,则必须使用'runOnUiThread()'方法在UI线程上访问它们。 – 2013-03-18 08:28:16

+3

是否有任何特别的原因,不使用服务 – DeltaCap 2013-03-18 08:29:49

+0

这是不推荐。连续运行会排出设备电池。 – HelmiB 2013-03-18 08:32:28

回答

17

我想一些代码在后台持续运行。我不希望 在服务中执行此操作。有没有其他方法可行?

您正在寻找的最有可能的机械化是AsyncTask。它直接指定用于在后台线程上执行后台进程。另外它的主要好处是提供了一些在Main(UI)线程上运行的方法,并且如果您想要向用户宣传任务中的某些进度或使用从后台进程检索的数据更新UI,则可以更新您的UI。

如果你不知道如何从这里开始是很好的教程:

注:也有可能使用IntentServiceResultReceiver的作品也是如此。

+0

谢谢你Sajmon。我会试试这个 – user2082987 2013-03-18 08:40:33

+0

sory如果我问的是愚蠢的问题 – user2082987 2013-03-18 09:29:52

+0

@ user2082987那么你尝试过吗? – Sajmon 2013-03-18 09:32:52

26

对于长期的后台进程,线程对于Android来说并不是最佳的。然而,这是代码,并且需要您自担风险...

记住服务或线程将在后台运行,但我们的任务需要使触发器(一次又一次调用)来获取更新,即一旦任务完成后,我们需要回顾下次更新的功能。

定时器(周期性触发器),报警(时基触发器),广播(事件基本触发器),递归将唤醒我们的功能。

public static boolean isRecursionEnable = false; 

void runInBackground() { 
    if (isRecursionEnable) 
     return; // Handle not to start multiple parallel threads 

    isRecursionEnable = true; // on exception on thread make it true again 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      // DO your work here 
      // get the data 
      if (activity_is_not_in_background) { 
       runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 
         //uddate UI 
         runInBackground(); 
        } 
       }); 
      } else { 
       runInBackground(); 
      } 
     } 
    }).start(); 
} 
+5

不要忘记在新线程上调用.start()(...) – dwbrito 2014-10-22 00:07:46

+0

您是否推荐这种方法在后台运行平均20分钟的自定义SignalStrengthListener,同时每秒从监听器中获取一次值更新UI线程?这里是更多的上下文:http://stackoverflow.com/questions/36167719/asynctask-fatal-exception-when-calling-a-method-from-doinbackground?noredirect=1#comment59973788_36167719 – JParks 2016-03-23 01:58:49

2

AsyncTask的替代方法是robospice。 https://github.com/octo-online/robospice

robospice的一些功能。

1.异步执行(在后台AndroidService中)网络请求(例如:使用Spring Android的REST请求)。在结果准备就绪时,在UI线程上通知应用程序。

2.is strong typed!您使用POJO提出您的请求,并根据请求结果获得POJO。

3.enforce对请求使用的POJO和您在项目中使用的Activity类都没有约束。 (使用Jackson和Gson,或者Xml,或者平面文本文件,或者二进制文件,甚至使用ORM Lite)的结果(在Json中)。

5.notifies网络请求的结果,你的活动(或其他任何情况下)当且仅当他们还活着

6。完全没有内存泄漏,比如Android Loaders,与Android AsyncTasks不同,它会通过你的UI线程通知你的活动。

7.使用简单但强大的异常处理模型。

样本开始。 https://github.com/octo-online/RoboSpice-samples

robospice样本https://play.google.com/store/apps/details?id=com.octo.android.robospice.motivations&feature=search_result

+0

如何将从网络获得的数组存储到SQLite的?基本上我想:从网络获取数据并将它们保存到我的SQLite中 - 都在后台线程中,然后让我的UI通知刷新ListView。我通常使用IntentService来完成,但RoboSpice的输入较少。 – Yar 2016-03-03 18:04:02

+0

@yar如果长时间运行,您可以使用意向服务。你也可以使用asynctask,但只能在短时间内使用。你可以创建一个线程,并在那里做所有的东西。现在我很久没有使用过robospice了。还有其他网络库像凌空... – Raghunandan 2016-03-04 06:02:12

+0

好的谢谢。我想过使用Robospice,但它看起来不太适合我的需求(灵活)。我长期使用IntentService取得成功。 – Yar 2016-03-04 10:42:21

219

如果您需要:

  1. 在后台线程上执行代码

  2. 执行代码不触及/更新UI

  3. 执行(短)的代码,将采取最多只需几秒钟即可完成

THEN使用下面的清洁和高效的模式,它使用的AsyncTask:

AsyncTask.execute(new Runnable() { 
    @Override 
    public void run() { 
     //TODO your background code 
    } 
}); 
+6

注意:需要API等级11 – friederbluemle 2015-11-25 14:06:17

+0

我使用上述代码发送的电子邮件与UI没有链接。这是第一次,它工作正常,但如果我尝试再次执行相同的代码,我的应用程序卡住了。 我应该在执行代码后终止AsyncTask吗? – 2016-10-21 16:51:37

+1

为什么不使用以下更轻量级的方法:new Thread(new Runnable(){ @Override public void run(){ // background code } }}。start(); – awardak 2017-05-13 15:59:32

0
class Background implements Runnable { 
    private CountDownLatch latch = new CountDownLatch(1); 
    private Handler handler; 

    Background() { 
     Thread thread = new Thread(this); 
     thread.start(); 
     try { 
      latch.await(); 
     } catch (InterruptedException e) { 
      /// e.printStackTrace(); 
     } 
    } 

    @Override 
    public void run() { 
     Looper.prepare(); 
     handler = new Handler(); 
     latch.countDown(); 
     Looper.loop(); 
    } 

    public Handler getHandler() { 
     return handler; 
    } 
} 
+0

欢迎来到StackOverflow。只有代码在他们的答案往往会被标记为删除,因为他们是“低质量”。请阅读关于回答问题的帮助部分,然后考虑在答案中添加一些评论。 – Graham 2018-03-03 18:16:09

相关问题