如何在 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();
}




} 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


}
260519 次浏览

我需要一些代码在后台连续运行 有没有其他可能的方法?

您最有可能寻找的机械装置是 AsyncTask。它直接指定用于在后台线程上执行后台进程。另外,它的主要优点是提供了一些方法,运行在主(UI)线程,使更新您的 UI 成为可能,如果你想通知用户有关任务的一些进展或更新用户界面从后台处理检索的数据。

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

注意: 也有可能使用 IntentServiceResultReceiver一起工作。

记住运行后台,连续运行是两个不同的任务。

对于长期的后台进程来说,线程在 Android 中并不是最佳选择。

为了以正确的方式接近它,您需要先启动服务,在服务内部,您需要启动需要 Runnable 的 Thread/Async 任务。

“记住服务和线程”将在后台运行,但是我们的任务需要使用触发器(一次又一次地调用)来获取更新,也就是说,一旦任务完成,我们需要为下一次更新调用该函数。

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

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();
}

使用服务: 如果您启动一个服务,它将启动,它将执行任务,如果服务不是 STICKY,它将在任务执行后终止自己。此服务终止也可能是由于代码中的异常或用户通过设置手动终止了该异常造成的。

START _ STICKY (粘性服务)是 Android 提供的选项,如果服务终止,服务将重新启动自身。

还记得多处理和多线程之间的差异吗? 服务是一个后台过程(就像没有 UI 的活动一样) , 如何在活动中启动线程以避免 MainThread (Activity/UI 线程)上的负载,如何在服务上启动线程以避免服务上的负载。

在单个语句中,如果希望运行一个后台继续任务,则需要启动一个 StickyService 并在事件基础上运行服务中的线程

AsyncTask 的一个替代品是 robospice。

机器人香料的一些特性。

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

是强类型的! 您使用 POJO 发出请求,并得到 POJO 作为请求结果。

3. 不对用于请求的 POJO 或项目中使用的活动类强制约束。

4.缓存结果(在 Json 中同时使用 Jackson 和 Gson,或者 XML,或者平面文本文件,或者二进制文件,甚至使用 ORM Lite)。

5.当且仅当网络请求的结果仍然存在时,才通知您的活动(或任何其他上下文)

6.根本没有内存泄漏,就像 Android Loader,不像 Android AsyncTask 在 UI Thread 上通知你的活动。

使用一个简单但是健壮的异常处理模型。

从样品开始。

https://play.google.com/store/apps/details?id=com.octo.android.robospice.motivations&feature=search_result机器人香料样品。

更新: 以上答案不再有效。使用 kotlin 协程进行后台线程。

如有需要:

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

  2. 执行不触及/更新用户界面的代码

  3. 执行(短)代码,最多需要几秒钟才能完成

然后使用以下使用 AsyncTask 的干净而有效的模式:

AsyncTask.execute(new Runnable() {
@Override
public void run() {
//TODO your background code
}
});
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;
}
}

如果你需要用不同的代码运行线程,这里有一个例子:

听众:

public interface ESLThreadListener {


public List onBackground();


public void onPostExecute(List list);


}

线程类

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;
}
}

运行不同的代码:

  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();

简单的三线

这样做的一个简单方法,我在 布兰登 · 鲁德的回答@ awardak评论中发现:

new Thread( new Runnable() { @Override public void run() {
// Run whatever background code you want here.
} } ).start();

我不知道是否,或如何,这是比使用 AsyncTask.execute更好,但它似乎为我们工作。任何关于差异的意见将不胜感激。

谢谢 @ awardak

今天我在找这个,布兰登・鲁德先生给了我一个 答得好。不幸的是,AsyncTask现在是 不赞成。你仍然可以使用它,但它会给你一个警告,这是非常恼人的。因此,另一种方法是像这样使用 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
}
*/
})


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
});
*/
});

//为我准确地工作

new Thread( () -> {
//run code on background thread
        

activity.runOnUiThread(()->{
//update the UI on main thread
});


//here activity is the reference of activity
    

            

}).start();

//或

 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
}
})