2013-03-18 78 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

相關問題