如何在Android上的后台线程上运行代码?

问题描述 投票:94回答:6

我想要一些代码在后台持续运行。我不想在服务中这样做。还有其他方法吗?

我曾尝试在我的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();
                        }


                    } 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

    }
android multithreading
6个回答
319
投票

如果你需要:

  1. 在后台线程上执行代码
  2. 执行不触及/更新UI的代码
  3. 执行(短)代码,最多需要几秒钟才能完成

然后使用以下干净且高效的模式,它使用AsyncTask:

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

37
投票

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

对于长期后台进程,线程不是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();
}

使用服务:如果启动服务它将启动,它将执行任务,它将自行终止。任务执行后。终止也可能是由异常引起的,或者是用户从设置中手动杀死它。 START_STICKY(Sticky Service)是android给出的选项,如果服务终止,服务将自动重启。

还记得多处理和多线程之间的问题区别吗?服务是后台进程(就像没有UI的活动一样),与在活动中启动线程以避免在主线程(活动线程)上加载相同的方式,与在服务上启动线程(或异步任务)所需的方式相同避免服务负担。

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


19
投票

我想要一些代码在后台持续运行。我不想在服务中这样做。还有其他方法吗?

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

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

注意:也有可能使用IntentServiceResultReceiver也可以。


2
投票

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

robospice的一些特征。

1.异步执行(在后台AndroidService中)网络请求(例如:使用Spring Android的REST请求)。当UI结果准备就绪时,在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样本。


1
投票
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
投票

如果您需要使用不同的代码预先运行线程,例如:

监听器:

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();
© www.soinside.com 2019 - 2024. All rights reserved.