我想要一些代码在后台持续运行。我不想在服务中这样做。还有其他方法吗?
我已尝试在Thread
中调用Activity
课程,但我的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
答案 0 :(得分:310)
如果您需要:
在后台线程上执行代码
执行不接触/更新UI的代码
执行(短)代码,最多需要几秒钟才能完成
然后使用以下干净且高效的模式,它使用AsyncTask:
AsyncTask.execute(new Runnable() {
@Override
public void run() {
//TODO your background code
}
});
答案 1 :(得分:34)
对于长期后台进程,线程不是Android的最佳选择。但是,这是代码,并且风险自负......
请记住服务或线程将在后台运行,但我们的任务需要触发(一次又一次地调用)以获取更新,即一旦任务完成,我们需要调用该功能以进行下一次更新。
定时器(周期性触发),闹钟(时基触发),广播(事件基础触发),递归将唤醒我们的功能。
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();
}
答案 2 :(得分:18)
我想要一些代码在后台持续运行。我不想要 在服务中做到这一点。还有其他方法吗?
您正在寻找的最有可能的机制是AsyncTask
。它直接指定用于在后台线程上执行后台处理。此外,它的主要优点是提供了一些在Main(UI)线程上运行的方法,如果您想要告知用户任务进度或使用从后台进程检索的数据更新UI,则可以更新UI。
如果您不知道如何从这里开始是很好的教程:
注意:此外,还可以使用IntentService
和ResultReceiver
同时使用。
答案 3 :(得分:4)
一种简单的操作方式,我在@awardak的Brandon Rude's answer中找到了这条评论:
new Thread( new Runnable() { @Override public void run() {
// Run whatever background code you want here.
} } ).start();
我不确定这是否或如何比使用AsyncTask.execute
更好,但这似乎对我们有用。关于差异的任何评论将不胜感激。
谢谢@awardak!
答案 4 :(得分:2)
AsyncTask的替代方案是robospice。 https://github.com/octo-online/robospice
robospice的一些功能。
1.异步执行(在后台AndroidService中)网络请求(例如:使用Spring Android的REST请求)。在UI线程上,当结果准备好时,通知你应用程序。
2.强类型!您使用POJO发出请求,并获得POJO作为请求结果。
3.对用于请求的POJO和您在项目中使用的Activity类都没有约束。
4.caches结果(在Json中使用Jackson和Gson,或Xml,或平面文本文件,或二进制文件,甚至使用ORM Lite)。
5.当您的活动(或任何其他上下文)显示网络请求的结果时,当且仅当它们仍然存在时
6.完全没有内存泄漏,比如Android Loaders,不像Android AsyncTasks通过他们的UI线程通知你的活动。
7.使用简单但强大的异常处理模型。
开始的样品。 https://github.com/octo-online/RoboSpice-samples
https://play.google.com/store/apps/details?id=com.octo.android.robospice.motivations&feature=search_result的robospice样本。
答案 5 :(得分:0)
如果您需要使用不同的代码预先运行线程,请参见以下示例:
监听器:
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();
答案 6 :(得分:0)
今天我正在寻找这个,布兰登·鲁德先生给了excellent answer。不幸的是,AsyncTask
现在是depricated,您仍然可以使用它,但是它给您一个警告,非常烦人。因此,另一种方法是像这样Executors
中使用kotlin
:
val someRunnable = object : Runnable{
override fun run() {
// todo: do your background tasks
requireActivity().runOnUiThread{
// update views / ui if you are in a fragment
};
/*
runOnUiThread {
// update ui if you are in an activity
}
* */
}
};
Executors.newSingleThreadExecutor().execute(someRunnable);
在java
中看起来像这样:
Runnable someRunnable = new Runnable() {
@Override
public void run() {
// todo: background tasks
runOnUiThread(new Runnable() {
@Override
public void run() {
// todo: update your ui / view in activity
}
});
/*
requireActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
// todo: update your ui / view in Fragment
}
});*/
}
};
Executors.newSingleThreadExecutor().execute(someRunnable);