简体   繁体   English

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

[英]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:如果你需要:

  1. execute code on a background Thread在后台线程上执行代码

  2. execute code that DOES NOT touch/update the UI执行不接触/更新 UI 的代码

  3. 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 并在事件库的服务中运行线程

Simple 3-Liner简单的 3 线

A simple way of doing this that I found as a comment by @awardak in Brandon Rude's answer :我发现了一种简单的方法,这是@awardakBrandon 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.任何关于差异的评论将不胜感激。

Thanks, @awardak !谢谢, @awardak

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.注意:也有可能将IntentServiceResultReceiver一起使用。

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.

相关问题 如何在后台运行此 Android 代码 - How can I run this Android code in Background 我可以无限期地在 Android 中运行后台线程吗? - Can I run a background thread in Android indefinitely? 如何在Thread中运行Web服务代码? - how can i run Webservice code in Thread? 如何在Android的后台运行图像? - How can I run image in the background in Android? 我如何在后台线程中运行 onNavigationItemSelected 方法 - how i can run the onNavigationItemSelected method in background thread 在Android中,如何在主线程中运行后台线程代码并获取返回值? - In Android , how to Run background thread code in main thread and get value returned? Android:为什么此代码无法在onCreate中运行,或者如何在没有线程的情况下使其运行? - Android: Why won't this code run in onCreate, or how can I make it work without a thread? 我如何在Android上创建在后台运行的线程 - How can i create a Thread that running on background on Android 如何在android的线程中运行函数? - How can I run my function in a thread in android? 如何在 flutter 的后台运行 dart 代码? - How can I run dart code in the background in flutter?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM