मैं एंड्रॉइड पर पृष्ठभूमि थ्रेड पर कोड कैसे चला सकता हूं?


131

मैं लगातार पृष्ठभूमि में कुछ कोड चलाना चाहता हूं। मैं इसे एक सेवा में नहीं करना चाहता। क्या कोई और रास्ता संभव है?

मैंने 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

    }

1
नमस्ते। क्या आपने जो कोशिश की है उसके उदाहरण के रूप में कुछ कोड पोस्ट कर सकते हैं? बैकग्राउंड थ्रेड पर कोड को चलाने के लिए अलग-अलग तरीके हैं लेकिन आपको याद रखना चाहिए कि यदि आप किसी भी यूआई घटकों को एक्सेस कर रहे हैं तो आपको यूआई थ्रेड पर उन्हें runOnUiThread()विधि का उपयोग करके एक्सेस करना होगा ।
एलेक्स वेइसे

3
क्या सेवा का उपयोग न करने का कोई विशेष कारण है
DeltaCap019

यह अनुशंसित नहीं है। लगातार चलने से डिवाइस की बैटरी खत्म हो जाएगी।
हेल्मीबी

मैंने कोड भेज दिया है।
user2082987

मैंने इसे सेवा में उपयोग करने की कोशिश की, लेकिन कई बार एक ही रिकॉर्ड भेजा।
user2082987

जवाबों:


379

अगर आप की जरूरत है:

  1. एक पृष्ठभूमि थ्रेड पर कोड निष्पादित करें

  2. कोड निष्पादित करें जो UI को स्पर्श / अपडेट नहीं करता है

  3. निष्पादित (संक्षिप्त) कोड जो पूरा होने में कुछ सेकंड में ले जाएगा

निम्न स्वच्छ और कुशल पैटर्न का उपयोग करें जो AsyncTask का उपयोग करता है:

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

10
नोट: एपीआई स्तर ११ की आवश्यकता है
१४-२२ पर तले हुए बियरबूमेले

9
आप निम्न का उपयोग क्यों नहीं करेंगे जो अधिक हल्का है: नया थ्रेड (नया रननेबल () {@ ओवरराइड सार्वजनिक शून्य रन () {// बैकग्राउंड कोड}})। प्रारंभ ();
अवार्ड

3
क्या इससे मेमोरी लीक होने की संभावना है?
हिलफ्रिट्ज

5
एक बात का ध्यान रखें कि AsyncTasks क्यूईट हैं। यदि आप सर्वर एपीआई कॉल के एक समूह के लिए इसका उपयोग करते हैं, तो वे समानांतर में नहीं चलेंगे।
रॉबर्ट्स


45

रनिंग बैकग्राउंड याद रखें, लगातार रन करना दो अलग-अलग काम हैं।

लंबी अवधि की पृष्ठभूमि प्रक्रियाओं के लिए, थ्रेड एंड्रॉइड के साथ इष्टतम नहीं हैं। हालाँकि, यहाँ कोड है और इसे अपने जोखिम पर करें ...

याद रखें कि सेवा या थ्रेड पृष्ठभूमि में चलेगा, लेकिन हमारे कार्य को अपडेट प्राप्त करने के लिए ट्रिगर (बार-बार कॉल) करने की आवश्यकता है, अर्थात एक बार कार्य पूरा होने के बाद हमें अगले अपडेट के लिए फ़ंक्शन को याद करने की आवश्यकता है।

टाइमर (आवधिक ट्रिगर), अलार्म (टाइमबेस ट्रिगर), ब्रॉडकास्ट (इवेंट बेस ट्रिगर), रिकर्सन अपने कार्यों को जागृत करेगा।

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 (स्टिकी सेवा) Android द्वारा दिया गया विकल्प है जो सेवा समाप्त होने पर सेवा स्वयं को पुनः आरंभ करेगा।

मल्टीप्रोसेसिंग और मल्टीथ्रेडिंग के बीच प्रश्न अंतर याद है? सेवा एक पृष्ठभूमि प्रक्रिया है (बस यूआई के बिना गतिविधि), जिस तरह से आप मुख्य धागा (गतिविधि धागा) पर लोड से बचने के लिए गतिविधि में थ्रेड लॉन्च करते हैं, उसी तरह आपको सेवा पर थ्रेड (या async कार्य) लॉन्च करने की आवश्यकता होती है सेवा पर भार से बचने के लिए।

एक कथन में, यदि आप चाहते हैं कि एक रन बैकग्राउंड टास्क जारी रहे, तो आपको स्टिकी सर्विस शुरू करने और इवेंट बेस में सर्विस में थ्रेड चलाने की आवश्यकता है


क्या आप यूआई थ्रेड को अपडेट करने के लिए प्रति सेकंड एक बार श्रोता से मान हथियाने के साथ-साथ औसतन 20 मिनट के लिए बैकग्राउंड में कस्टम सिग्नलस्ट्रीमलिस्टनर चलाने की इस विधि की सिफारिश करेंगे? यहाँ अधिक संदर्भ है: stackoverflow.com/questions/36167719/…
JParks 1

यदि आप 'isRecursionEnable = true' सेट करते हैं तो प्रक्रिया फिर से कैसे चलती है? फिर आप 'runInBackground ()' के लिए 'रन' विधि के अंदर कॉल करते हैं, यह फ़ंक्शन की शुरुआत में स्टेटमेंट में कैसे दर्ज नहीं होगा?
मिकी

23

मैं लगातार पृष्ठभूमि में कुछ कोड चलाना चाहता हूं। मैं इसे एक सेवा में नहीं करना चाहता। क्या कोई और रास्ता संभव है?

सबसे अधिक संभावना मैकेनिज्म है जिसे आप ढूंढ रहे हैं AsyncTask। यह सीधे पृष्ठभूमि थ्रेड पर पृष्ठभूमि की प्रक्रिया को करने के लिए नामित है। इसके अलावा इसका मुख्य लाभ यह है कि कुछ तरीके हैं जो मुख्य (UI) थ्रेड पर चलते हैं और यदि आप कार्य में कुछ प्रगति के बारे में उपयोगकर्ता को सूचित करना चाहते हैं या पृष्ठभूमि प्रक्रिया से पुनर्प्राप्त डेटा के साथ यूआई को अपडेट करना चाहते हैं तो अपने यूआई को अपडेट करना संभव है।

यदि आप नहीं जानते कि यहाँ कैसे शुरू करना अच्छा ट्यूटोरियल है:

नोट: इसके अलावा उपयोग करने के लिए संभावना है IntentServiceके साथ ResultReceiverकि काम करता है और साथ ही।


@ user2082987 तो क्या आपने इसे आजमाया?
शमौन डोरोयाक

AsyncTask के ये पैरामीटर भ्रामक हैं
user2082987

AsyncTask किसी भी तरह थ्रेड के चारों ओर एक आवरण है, इसलिए यह एंड्रॉइड की समस्या को हल नहीं करता है जिससे एप्लिकेशन को पृष्ठभूमि में रहते हुए मार दिया जाता है
लस्सी किन्नुनेन

हाय @LassiKinnunen मैंने लिखा है कि 5 साल पहले जवाब। अब सब कुछ बदल गया है और मैं वर्तमान में AsyncTask का उपयोग नहीं कर रहा हूं क्योंकि इसकी मेमोरी लीक सुरक्षित नहीं है।
साइमन डोरोयाकॉक

हां, मुझे एहसास है कि लेकिन लोग अभी भी इसे Google के माध्यम से ढूंढेंगे और मैंने लोगों के बहुत सारे कमेंट्स देखे हैं, जबकि यह बिना किसी उद्देश्य के लिए बहुत कम सेवा करने पर भी Google रैपर का उपयोग करने की सलाह देता है। मूल प्रश्न के रूप में यदि कोई 2018 में कुछ उत्तरों की तलाश कर रहा है, तो एक सेवा बनाएं और इसे लॉन्च करें और इसे अधिसूचना के साथ अग्रभूमि में चिह्नित करें यदि आप इसे मारने की संभावना को अधिकतम करना चाहते हैं। वास्तविक लंबी चलने की प्रक्रिया को हैंडलर्स या एक अलग धागे के साथ संभाला जा सकता है। एहसास नहीं था कि वे वास्तव में इसे स्मृति रिसाव को सुरक्षित नहीं बना पाए थे?
लस्सी किन्नुनेन

16

सरल 3-लाइनर

ऐसा करने का एक सरल तरीका जो मुझे ब्रैंडन रूड के जवाब में @awardak द्वारा एक टिप्पणी के रूप में मिला :

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

मुझे यकीन नहीं है कि, या कैसे, यह उपयोग करने से बेहतर है AsyncTask.executeलेकिन यह हमारे लिए काम करता है। अंतर के रूप में किसी भी टिप्पणी की सराहना की जाएगी।

धन्यवाद, @awardak !


हम थ्रेड रन विधि के अंदर मुख्य थ्रेड पर वापस पोस्ट करने के लिए हैंडलर.पोस्ट () विधि का उपयोग करते हैं।
androidXP

2

AsyncTask का एक विकल्प है रोबोस्पाइस। https://github.com/octo-online/robospice

डकैती की कुछ विशेषताएं।

1.executes एसिंक्रोनस रूप से (एक पृष्ठभूमि AndroidService में) नेटवर्क अनुरोध (उदा: स्प्रिंग एंड्रॉइड का उपयोग करने के लिए अन्य अनुरोध)। यूआई थ्रेड पर, ऐप को सूचित करें, जब परिणाम तैयार होता है।

2. जोर से टाइप किया! आप POJO का उपयोग करके अपने अनुरोध करते हैं और आपको अनुरोध परिणाम के रूप में POJO मिलते हैं।

3. लागू किए गए अनुरोधों के लिए न तो POJOs पर और न ही आपके प्रोजेक्ट्स में उपयोग की जाने वाली गतिविधि कक्षाओं पर कोई अड़चन नहीं।

4. कैश परिणाम (जैक्सन और गन्सन, या एक्सएमएल, या फ्लैट पाठ फ़ाइलों, या बाइनरी फ़ाइलों, यहां तक ​​कि ओआरएम लाइट का उपयोग करके दोनों के साथ जसन में)।

5. आपकी गतिविधियों (या किसी अन्य संदर्भ) को नेटवर्क अनुरोध के परिणाम को सूचित करता है यदि और केवल यदि वे अभी भी जीवित हैं

6. एंड्रॉइड लोडर की तरह, सभी पर एंड्रॉइड लोडर की तरह मेमोरी मेमोरी लीक नहीं होती है, बल्कि यूआई थ्रेड पर आपकी गतिविधियों को सूचित करता है।

7. एक सरल लेकिन मजबूत अपवाद हैंडलिंग मॉडल।

से शुरू करने के लिए नमूने। https://github.com/octo-online/RoboSpice-samples

पर robospice का एक नमूना https://play.google.com/store/apps/details?id=com.octo.android.robospice.motivations&feature=search_result


SQLite नेटवर्क से प्राप्त सरणी को कैसे स्टोर करें? मूल रूप से मैं यह चाहूंगा: नेटवर्क से डेटा प्राप्त करें और उन्हें मेरी SQLite में सहेजें - दोनों पृष्ठभूमि थ्रेड में, फिर मेरे UI को नए सिरे से देखने के लिए सूचित करें। मैं इसे आमतौर पर IntentService के साथ करता हूं, लेकिन RoboSpice कम टाइपिंग है।
यार

@ यदि आप एक लंबे समय तक चलने वाले ऑपरेशन के लिए एक इरादे सेवा का उपयोग कर सकते हैं। इसके अलावा आप asynctask का उपयोग कर सकते हैं लेकिन केवल अगर इसकी छोटी अवधि के लिए। आप एक धागा बना सकते हैं और वहां अपना सारा सामान रख सकते हैं। मैंने अब लंबे समय तक रोबोस्पाइस का इस्तेमाल नहीं किया है। वॉली जैसी अन्य नेटवर्किंग लाइब्रेरी हैं ...
रघुनंदन

ठीक है धन्यवाद। मैंने रोबोस्पाइस का उपयोग करने के बारे में सोचा, लेकिन ऐसा लगता है कि यह मेरी जरूरतों के लिए बहुत अच्छा (लचीला) नहीं है। मैं सफलता के साथ लंबे समय तक IntentService का उपयोग करता हूं।
यार

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

5
StackOverflow में आपका स्वागत है। उनमें केवल कोड वाले उत्तर हटाए जाने के लिए ध्वजांकित होते हैं क्योंकि वे "निम्न गुणवत्ता" हैं। कृपया प्रश्नों के उत्तर देने में सहायता अनुभाग पढ़ें फिर अपने उत्तर में कुछ टिप्पणी जोड़ने पर विचार करें।
ग्राहम

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();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.