Bagaimana saya bisa menjalankan kode pada utas latar di Android?

131

Saya ingin beberapa kode berjalan di latar belakang terus menerus. Saya tidak ingin melakukannya di layanan. Apakah ada cara lain yang memungkinkan?

Saya telah mencoba memanggil Threadkelas di Activitytetapi saya Activitytetap di latar belakang untuk beberapa waktu dan kemudian berhenti. The Threadkelas juga berhenti bekerja.

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

    }
pengguna2082987
sumber
1
Hai. Bisakah Anda memposting beberapa kode sebagai contoh dari apa yang Anda coba? Ada berbagai cara untuk menjalankan kode pada utas latar belakang tetapi Anda harus ingat jika Anda mengakses komponen UI apa pun Anda harus mengaksesnya pada utas UI dengan menggunakan runOnUiThread()metode ini.
Alex Wiese
3
Apakah ada alasan khusus untuk tidak menggunakan Layanan
DeltaCap019
ini tidak direkomendasikan. berjalan terus menerus akan menguras baterai perangkat.
HelmiB
Saya sudah mengirim kodenya.
user2082987
Saya mencoba menggunakannya dalam layanan tetapi mengirimkan catatan yang sama beberapa kali.
user2082987

Jawaban:

379

JIKA Anda perlu:

  1. mengeksekusi kode pada utas latar belakang

  2. jalankan kode yang TIDAK menyentuh / memperbarui UI

  3. mengeksekusi kode (pendek) yang akan membutuhkan waktu paling lama beberapa detik untuk menyelesaikannya

LALU menggunakan pola bersih dan efisien berikut yang menggunakan AsyncTask:

AsyncTask.execute(new Runnable() {
   @Override
   public void run() {
      //TODO your background code
   }
});
Brandon Rude
sumber
10
Catatan: Memerlukan API level 11
friederbluemle
9
Mengapa Anda tidak menggunakan yang berikut ini yang lebih ringan: new Thread (new Runnable () {@Override public void run () {// kode latar belakang}}). Start ();
awardak
3
Apakah ada kemungkinan ini menyebabkan kebocoran memori?
Hilfritz
5
Satu hal yang perlu diperhatikan adalah AsyncTasks di-queued. Jika Anda menggunakan ini untuk sekelompok panggilan api server, mereka tidak akan berjalan secara paralel.
Chase Roberts
45

Ingat Menjalankan Latar Belakang, Berlari terus menerus adalah dua tugas yang berbeda.

Untuk proses latar belakang jangka panjang, Threads tidak optimal dengan Android. Namun, inilah kodenya dan lakukan dengan risiko Anda sendiri ...

Ingat Layanan atau Utas akan berjalan di latar belakang tetapi tugas kita perlu membuat pemicu (menelepon lagi dan lagi) untuk mendapatkan pembaruan, yaitu setelah tugas selesai kita perlu mengingat fungsi untuk pembaruan berikutnya.

Timer (pemicu periodik), Alarm (pemicu Timebase), Siaran (Pemicu basis acara), rekursi akan membangunkan fungsi kita.

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

Menggunakan Layanan: Jika Anda meluncurkan Layanan itu akan mulai, Itu akan menjalankan tugas, dan itu akan berakhir dengan sendirinya. setelah eksekusi tugas. dihentikan mungkin juga disebabkan oleh pengecualian, atau pengguna membunuhnya secara manual dari pengaturan. START_STICKY (Sticky Service) adalah opsi yang diberikan oleh android bahwa layanan akan memulai ulang sendiri jika layanan dihentikan.

Ingat perbedaan pertanyaan antara multiprosesing dan multithreading? Layanan adalah proses latar belakang (Sama seperti aktivitas tanpa UI), Cara yang sama cara Anda meluncurkan utas dalam aktivitas untuk menghindari memuat pada utas utama (Utas aktivitas), cara yang sama Anda harus meluncurkan utas (atau tugas asinkron) pada layanan untuk menghindari memuat layanan.

Dalam satu pernyataan, jika Anda ingin menjalankan latar belakang melanjutkan tugas, Anda perlu meluncurkan StickyService dan menjalankan utas dalam layanan pada basis acara

Sandeep P
sumber
Apakah Anda merekomendasikan metode ini untuk menjalankan SignalStrengthListener kustom di latar belakang selama rata-rata 20 menit, sambil mengambil nilai dari pendengar sekali per detik untuk memperbarui utas UI? Berikut ini lebih banyak konteks: stackoverflow.com/questions/36167719/…
JParks
Bagaimana proses berjalan lagi jika Anda menetapkan 'isRecursionEnable = true'? Anda kemudian memanggil di dalam metode 'run' untuk 'runInBackground ()', bagaimana itu tidak akan memasukkan pernyataan if di awal fungsi?
Mickey
23

Saya ingin beberapa kode berjalan di latar belakang terus menerus. Saya tidak ingin melakukannya di layanan. Apakah ada cara lain yang memungkinkan?

Kemungkinan besar mekanizm yang Anda cari adalah AsyncTask. Itu langsung ditunjuk untuk melakukan proses latar belakang di latar belakang Thread. Juga manfaat utamanya adalah menawarkan beberapa metode yang berjalan di Utas Utama (UI) dan memungkinkan untuk memperbarui UI Anda jika Anda ingin memberi tahu pengguna tentang beberapa kemajuan dalam tugas atau memperbarui UI dengan data yang diambil dari proses latar belakang.

Jika Anda tidak tahu bagaimana memulainya di sini adalah tutorial yang bagus:

Catatan: Juga ada kemungkinan untuk digunakan IntentServicedengan ResultReceiveryang berfungsi juga.

Simon Dorociak
sumber
@ user2082987 jadi apakah Anda mencobanya?
Simon Dorociak
parameter-parameter asyncTask ini membingungkan
user2082987
Bagaimanapun, AsyncTask hanyalah pembungkus di Thread, jadi itu tidak menyelesaikan masalah Android yang membunuh aplikasi saat berada di latar belakang
Lassi Kinnunen
Hai @LassiKinnunen Saya menulis jawaban itu 5 tahun yang lalu. Sekarang semuanya berubah dan saya saat ini tidak menggunakan AsyncTask karena memorinya bocor tidak aman.
Simon Dorociak
Ya saya menyadari itu, tetapi orang-orang masih akan menemukan ini melalui google dan saya telah melihat begitu banyak komentar orang merekomendasikan menggunakan pembungkus google bahkan ketika itu melayani sedikit atau tanpa tujuan, maaf. Adapun pertanyaan awal jika seseorang mencari beberapa jawaban di 2018, buat layanan dan luncurkan dan tandai sebagai di latar depan dengan pemberitahuan jika Anda ingin memaksimalkan peluang itu tidak terbunuh. Proses jangka panjang yang sebenarnya dapat ditangani dengan penangan atau utas terpisah. Tidak menyadari bahwa mereka berhasil membuat itu bukan kebocoran memori yang aman?
Lassi Kinnunen
16

3-Liner sederhana

Cara sederhana untuk melakukan ini yang saya temukan sebagai komentar oleh @awardak dalam jawaban Brandon Rude :

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

Saya tidak yakin apakah, atau bagaimana, ini lebih baik daripada menggunakan AsyncTask.executetetapi tampaknya bekerja untuk kita. Setiap komentar tentang perbedaannya akan dihargai.

Terima kasih, @awardak !

Joshua Pinter
sumber
kami menggunakan metode handler.post () untuk mempostingnya kembali di utas utama di dalam metode run Thread.
androidXP
2

Alternatif untuk AsyncTask adalah robospice. https://github.com/octo-online/robospice .

Beberapa fitur robospice.

1. mengeksekusi permintaan jaringan yang tidak sinkron (di latar AndroidService) (mis: permintaan REST menggunakan Spring Android). Beri tahu aplikasi Anda, di utas UI, saat hasilnya siap.

2. sangat diketik! Anda membuat permintaan Anda menggunakan POJO dan Anda mendapatkan POJO sebagai hasil permintaan.

3. tidak membuat kendala baik pada POJO yang digunakan untuk permintaan maupun pada kelas Kegiatan yang Anda gunakan dalam proyek Anda.

4.caches hasil (dalam Json dengan Jackson dan Gson, atau Xml, atau file teks datar, atau file biner, bahkan menggunakan ORM Lite).

5. memberitahukan aktivitas Anda (atau konteks lainnya) dari hasil permintaan jaringan jika dan hanya jika masih hidup

6. tidak ada kebocoran memori sama sekali, seperti Android Loaders, tidak seperti Android AsyncTasks memberi tahu aktivitas Anda di Thread UI mereka.

7.menggunakan model penanganan pengecualian yang sederhana namun kuat.

Sampel untuk memulai. https://github.com/octo-online/RoboSpice-samples .

Contoh robospice di https://play.google.com/store/apps/details?id=com.octo.android.robospice.motivations&feature=search_result .

Raghunandan
sumber
Bagaimana cara menyimpan array yang diperoleh dari jaringan ke SQLite? Pada dasarnya saya ingin: mendapatkan data dari jaringan DAN menyimpannya ke SQLite saya - keduanya di latar belakang, kemudian mendapatkan UI saya diberitahu untuk menyegarkan ListView. Saya biasanya melakukannya dengan IntentService, tetapi RoboSpice kurang mengetik.
Yar
@yar Anda dapat menggunakan layanan maksud jika operasi yang berjalan lama. Anda juga dapat menggunakan asynctask tetapi hanya jika untuk jangka waktu pendek. Anda dapat membuat utas dan melakukan semua hal di sana. Saya sudah lama tidak menggunakan robospice. Ada perpustakaan jaringan lain seperti voli ...
Raghunandan
Ok terima kasih. Saya berpikir untuk menggunakan Robospice, tetapi sepertinya tidak terlalu bagus (fleksibel) untuk kebutuhan saya. Saya menggunakan IntentService untuk waktu yang lama dengan kesuksesan.
Yar
2
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;
    }
}
Geno Papashvili
sumber
5
Selamat datang di StackOverflow. Jawaban dengan hanya kode di dalamnya cenderung ditandai untuk dihapus karena "berkualitas rendah". Silakan baca bagian bantuan tentang menjawab pertanyaan, kemudian pertimbangkan untuk menambahkan beberapa komentar untuk Jawaban Anda.
Graham
0

Jika Anda perlu menjalankan utas dengan kode yang berbeda di sini adalah contoh:

Pendengar:

public interface ESLThreadListener {

    public List onBackground();

    public void onPostExecute(List list);

}

Kelas Utas

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

Jalankan kode yang berbeda:

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