[英]How can I run code on a background thread on Android?
I want some code to run in the background continuously.我希望一些代码在后台连续运行。 I don't want to do it in a service.
我不想在服务中这样做。 Is there any other way possible?
有没有其他可能的方法?
I have tried calling the Thread
class in my Activity
but my Activity
remains in the background for sometime and then it stops.我曾尝试在我的
Activity
中调用Thread
类,但我的Activity
会在后台停留一段时间然后停止。 The Thread
class also stops working. 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();
}
} else {
Thread.sleep( 60000 );
} // end of else
} 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
}
IF you need to:如果你需要:
execute code on a background Thread在后台线程上执行代码
execute code that DOES NOT touch/update the UI执行不接触/更新 UI 的代码
execute (short) code which will take at most a few seconds to complete执行(短)代码,最多需要几秒钟才能完成
THEN use the following clean and efficient pattern which uses AsyncTask:然后使用以下使用 AsyncTask 的简洁高效的模式:
AsyncTask.execute(new Runnable() {
@Override
public void run() {
//TODO your background code
}
});
Remember Running Background, Running continuously is two different tasks.记住运行背景,连续运行是两个不同的任务。
For long-term background processes, Threads aren't optimal with Android.对于长期后台进程,线程不是 Android 的最佳选择。 However, here's the code, and do it at your own risk.
但是,这是代码,请自行承担风险。
To approach it in the right way, you need to Start Service First, Inside the service, you need to start the Thread/Async task Which needs Runnable.要以正确的方式处理它,您需要首先启动服务,在服务内部,您需要启动需要可运行的线程/异步任务。
Remember Service and Thread will run in the background but our task needs to make triggers (call again and again) to get updates, ie once the task is completed we need to recall the function for the next update.请记住,Service 和 Thread 将在后台运行,但我们的任务需要触发(一次又一次调用)以获取更新,即一旦任务完成,我们需要调用函数以进行下一次更新。
Timer (periodic trigger), Alarm (Timebase trigger), Broadcast (Event base Trigger), recursion will awake our functions. Timer(周期性触发),Alarm(时基触发),Broadcast(事件基触发),递归会唤醒我们的函数。
public static boolean isRecursionEnable = true;
void runInBackground() {
if (!isRecursionEnable)
// Handle not to start multiple parallel threads
return;
// isRecursionEnable = false; when u want to stop
// 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() {
// update UI
runInBackground();
}
});
} else {
runInBackground();
}
}
}).start();
}
Using Service: If you launch a Service it will start, It will execute the task, and it will terminate itself after the task execution if the service is not STICKY.使用服务:如果你启动一个服务,它会启动,它会执行任务,如果服务不是 STICKY,它会在任务执行后自行终止。 This Service termination might also be caused by an exception in code or the user killed it manually from settings.
此服务终止也可能是由代码中的异常或用户从设置中手动终止的。
START_STICKY (Sticky Service) is the option given by Android that the service will restart itself if the service is terminated. START_STICKY(粘性服务)是 Android 提供的选项,如果服务终止,服务将自行重启。
Remember the question difference between multiprocessing and multithreading?还记得多处理和多线程之间的问题区别吗? Service is a background process (Just like activity without UI), The same way how you launch thread in the activity to avoid load on the MainThread (Activity/UI thread), the same way you need to launch threads on service to avoid load on service.
Service 是一个后台进程(就像没有 UI 的活动一样),与您在活动中启动线程以避免负载在 MainThread(活动/UI 线程)上的方式相同,您需要在服务上启动线程以避免负载的方式相同服务。
In a single statement, if you want a run a background continues task, you need to launch a StickyService and run the thread in the service on event base在单个语句中,如果要运行后台继续任务,则需要启动 StickyService 并在事件库的服务中运行线程
A simple way of doing this that I found as a comment by @awardak in Brandon Rude's answer :我发现了一种简单的方法,这是@awardak在Brandon Rude 的回答中的评论:
new Thread( new Runnable() { @Override public void run() {
// Run whatever background code you want here.
} } ).start();
I'm not sure if, or how, this is better than using AsyncTask.execute
but it seems to work for us.我不确定这是否或如何比使用
AsyncTask.execute
更好,但它似乎对我们有用。 Any comments as to the difference would be appreciated.任何关于差异的评论将不胜感激。
I want some code to run in the background continuously.
我希望一些代码在后台连续运行。 I don't want to do it in a service.
我不想在服务中这样做。 Is there any other way possible?
有没有其他可能的方法?
Most likely mechanizm that you are looking for is AsyncTask
.您正在寻找的最有可能的机制是
AsyncTask
。 It directly designated for performing background process on background Thread.它直接指定在后台线程上执行后台进程。 Also its main benefit is that offers a few methods which run on Main(UI) Thread and make possible to update your UI if you want to annouce user about some progress in task or update UI with data retrieved from background process.
此外,它的主要好处是提供了一些在主(UI)线程上运行的方法,如果您想向用户通知任务的某些进展或使用从后台进程检索的数据更新 UI,则可以更新您的 UI。
If you don't know how to start here is nice tutorial:如果您不知道如何从这里开始,这里有很好的教程:
Note: Also there is possibility to use IntentService
with ResultReceiver
that works as well.注意:也有可能将
IntentService
与ResultReceiver
一起使用。
Today I was looking for this and Mr Brandon Rude gave an excellent answer .今天我正在寻找这个,布兰登鲁德先生给出了一个很好的答案。 Unfortunately,
AsyncTask
is now deprecated .不幸的是,
AsyncTask
现在已弃用。 You can still use it, but it gives you a warning, which is very annoying.你仍然可以使用它,但它会给你一个警告,这很烦人。 So an alternative is to use
Executors
like this (in kotlin
):因此,另一种选择是使用这样的
Executors
(在kotlin
中):
Executors.newSingleThreadExecutor().execute(Runnable {
// todo: do your background tasks
runOnUiThread{
// update ui if you are in an activity
}
/*
requireActivity().runOnUiThread {
// update views / ui if you are in a fragment
}
*/
})
And in java
it looks like this:在
java
中它看起来像这样:
Executors.newSingleThreadExecutor().execute(() -> {
// todo: background tasks
runOnUiThread(() -> {
// todo: update your ui / view in activity
});
/*
requireActivity().runOnUiThread((Runnable) () -> {
// todo: update your ui / view in Fragment
});
*/
});
An Alternative to AsyncTask is robospice. AsyncTask 的替代方案是 robospice。 https://github.com/octo-online/robospice .
https://github.com/octo-online/robospice 。
Some of the features of robospice. robospice 的一些特性。
1.executes asynchronously (in a background AndroidService) network requests (ex: REST requests using Spring Android).notify you app, on the UI thread, when result is ready. 1. 异步执行(在后台 AndroidService 中)网络请求(例如:使用 Spring Android 的 REST 请求)。当结果准备好时,在 UI 线程上通知您的应用程序。
2.is strongly typed ! 2.强类型! You make your requests using POJOs and you get POJOs as request results.
您使用 POJO 提出请求,并获得 POJO 作为请求结果。
3.enforce no constraints neither on POJOs used for requests nor on Activity classes you use in your projects. 3. 对用于请求的 POJO 和您在项目中使用的 Activity 类均不实施任何限制。
4.caches results (in Json with both Jackson and Gson, or Xml, or flat text files, or binary files, even using ORM Lite). 4.caches 结果(在 Json 中同时包含 Jackson 和 Gson,或 Xml,或纯文本文件,或二进制文件,甚至使用 ORM Lite)。
5.notifies your activities (or any other context) of the result of the network request if and only if they are still alive 5.当且仅当它们仍然存在时,通知您的活动(或任何其他上下文)网络请求的结果
6.no memory leak at all, like Android Loaders, unlike Android AsyncTasks notifies your activities on their UI Thread. 6. 完全没有内存泄漏,就像 Android Loaders 一样,不像 Android AsyncTasks 在他们的 UI 线程上通知你的活动。
7.uses a simple but robust exception handling model. 7.使用简单但健壮的异常处理模型。
Samples to start with.样品开始。 https://github.com/octo-online/RoboSpice-samples .
https://github.com/octo-online/RoboSpice-samples 。
A sample of robospice at https://play.google.com/store/apps/details?id=com.octo.android.robospice.motivations&feature=search_result . https://play.google.com/store/apps/details?id=com.octo.android.robospice.motivations&feature=search_result上的 robospice 示例。
Update: The above is answer is not valid anymore.更新:以上是答案不再有效。 Use kotlin coroutines for background threading.
使用 kotlin 协程进行后台线程。
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;
}
}
If you need run thread predioticly with different codes here is example:如果您需要使用不同的代码预先运行线程,这里是示例:
Listener:听众:
public interface ESLThreadListener {
public List onBackground();
public void onPostExecute(List list);
}
Thread Class线程类
public class ESLThread extends AsyncTask<Void, Void, List> {
private ESLThreadListener mListener;
public ESLThread() {
if(mListener != null){
mListener.onBackground();
}
}
@Override
protected List doInBackground(Void... params) {
if(mListener != null){
List list = mListener.onBackground();
return list;
}
return null;
}
@Override
protected void onPostExecute(List t) {
if(mListener != null){
if ( t != null) {
mListener.onPostExecute(t);
}
}
}
public void setListener(ESLThreadListener mListener){
this.mListener = mListener;
}
}
Run different codes:运行不同的代码:
ESLThread thread = new ESLThread();
thread.setListener(new ESLThreadListener() {
@Override
public List onBackground() {
List<EntityShoppingListItems> data = RoomDB.getDatabase(context).sliDAO().getSL(fId);
return data;
}
@Override
public void onPostExecute(List t) {
List<EntityShoppingListItems> data = (List<EntityShoppingListItems>)t;
adapter.setList(data);
}
});
thread.execute();
//Works accurately for me //对我来说准确无误
new Thread( () -> {
//run code on background thread
activity.runOnUiThread(()->{
//update the UI on main thread
});
//here activity is the reference of activity
}).start();
//OR //或者
new Thread(new Runnable() {
@Override
public void run() {
//run code on background thread
activity.runOnUiThread(()->{
//update the UI on main thread
});
//here activity is the reference of activity
}
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.