वास्तव में पोस्ट विधि क्या करती है?


106

मुझे एक बहुत ही अजीब सुविधा का सामना करना पड़ा है।

जब मैं मुख्य धागे पर एक एनीमेशन चलाने की कोशिश कर रहा हूं, तो यह शुरू नहीं होता है। जब मैंने कहा एनीमेशन का उपयोग करते हुए

getView().post(new Runnable() {
            @Override
            public void run() {
                getView().startAnimation(a);
            }
        });

यह शुरू होता है।

मैंने CurrentThreadएनीमेशन शुरू करने से पहले प्रिंट किया है और दोनों प्रिंट main

जाहिर है, मुझे यहां कुछ याद आ रहा है, क्योंकि दोनों को मुख्य धागे पर एनीमेशन शुरू करना चाहिए ... मेरा अनुमान है कि जैसे ही पोस्ट कार्य को कतार में जोड़ता है, यह अधिक "सही समय" पर शुरू होता है, लेकिन मुझे जानना अच्छा लगेगा यहाँ और अधिक गहराई पर क्या होता है।

संपादित करें: मुझे चीजों को स्पष्ट करने दें - मेरा सवाल यह है कि पोस्ट पर एनीमेशन शुरू करने का कारण यह कैसे शुरू होता है, जब मुख्य धागे पर एनीमेशन शुरू नहीं होता है।


क्या यह व्यवहार Android संस्करण के लिए विशिष्ट है? मैं इसे एंड्रॉइड 4.1.2 पर पुन: पेश नहीं कर सका!
अकडनिज़

मैंने Android 2.3.3 पर इस व्यवहार को पुन: पेश किया। लेकिन के लिए AnimationDrawable! Animationप्रत्येक इंस्टालेशन पर साधारण उदाहरण सफलतापूर्वक शुरू हुआ। में AnimationDrawableमामले; जब आप इसे शुरू करने की कोशिश करते हैं onCreate, तो यह उस समय देखने के लिए संलग्न नहीं होने के कारण शुरू नहीं होता है। तो यह एक थ्रेडिंग मुद्दा नहीं है AnimationDrawable। शायद एक ही बात के लिए लागू होता है Animation? डेवलपर
Akdeniz

जवाबों:


161

पोस्ट : संदेश संदेश कतार में Runnable को पोस्ट करने का कारण बनता है,

Runnable: एक कमांड को निष्पादित करता है जिसे निष्पादित किया जा सकता है। अक्सर एक अलग थ्रेड में कोड चलाते थे।

रन () : क्लास के कोड के सक्रिय भाग को निष्पादित करना शुरू करता है। इस पद्धति को तब कहा जाता है जब एक धागा शुरू किया जाता है जिसे एक वर्ग के साथ बनाया गया है जो कि रननेबल को लागू करता है।

getView().post(new Runnable() {

         @Override
         public void run() {
             getView().startAnimation(a);
         }
     });

कोड :getView().startAnimation(a);

आपके कोड में,

संदेश कतार को जोड़ने के लिए रननेबल ( कोड अलग-अलग थ्रेड में चलाया जाएगा) पोस्ट का कारण बनता है ।

जब मैसेज क्यू से लाया जाता है तो एक नए सूत्र में प्रारंभ किया जाएगा

[संपादित 1]

हम UI थ्रेड (मुख्य थ्रेड) के बजाय नए थ्रेड का उपयोग क्यों करते हैं?

UI थ्रेड:

  • जब आवेदन शुरू किया जाता है, यूआई थ्रेड स्वचालित रूप से बनाया जाता है

  • यह घटनाओं को उचित विजेट में भेजने का प्रभारी है और इसमें ड्राइंग इवेंट शामिल हैं।

  • यह वह धागा भी है जिसके साथ आप एंड्रॉइड विजेट्स के साथ बातचीत करते हैं

उदाहरण के लिए, यदि आप स्क्रीन पर एक बटन स्पर्श करते हैं, तो UI थ्रेड स्पर्श ईवेंट को विजेट पर भेज देता है जो बदले में इसकी दबाया हुआ स्थिति सेट करता है और ईवेंट कतार में एक अमान्य अनुरोध पोस्ट करता है। UI थ्रेड अनुरोध को हटा देता है और विजेट को फिर से शुरू करने के लिए सूचित करता है।

यदि कोई उपयोगकर्ता एक बटन दबाता है जो लंबे समय तक चलेगा तो क्या होगा?

((Button)findViewById(R.id.Button1)).setOnClickListener(           
             new OnClickListener() {        
        @Override
    public void onClick(View v) {
            final Bitmap b = loadImageFromNetwork();
            mImageView.setImageBitmap(b);
}
});

यूआई जमा देता है। प्रोग्राम क्रैश भी हो सकता है।

public void onClick(View v) {
  new Thread(new Runnable() {
    public void run() {
        final Bitmap b = loadImageFromNetwork();
        mImageView.setImageBitmap(b);
    }
  }).start();
}

यह एंड्रॉइड नियम को तोड़ता है जो वर्कर थ्रेड से कभी भी यूआई को अपडेट नहीं करता है

एंड्रॉइड यूआई थ्रेड को अन्य थ्रेड्स से एक्सेस करने के कई तरीके प्रदान करता है।

  • Activity.runOnUiThread (Runnable)
  • View.post (Runnable)
  • View.postDelayed (चलाने योग्य, लंबा)
  • हैंडलर

नीचे की तरह,

View.post (Runnable)

public void onClick(View v) {
  new Thread(new Runnable() {
    public void run() {
      final Bitmap b = loadImageFromNetwork();
      mImageView.post(new Runnable() {
        public void run() {
          mImageView.setImageBitmap(b);
        }
      });
    }
  }).start();
}

हैंडलर

final Handler myHandler = new Handler(Looper.getMainLooper());

(new Thread(new Runnable() {

    @Override
    public void run() {
       final Bitmap b = loadImageFromNetwork();
      myHandler.post(new Runnable() {                           

        @Override
        public void run() {
           mImageView.setImageBitmap(b);
          }
        });
      }
    })).start();                
}

यहां छवि विवरण दर्ज करें

अधिक जानकारी के लिए

http://android-developers.blogspot.com/2009/05/painless-threading.html

http://www.aviyehuda.com/blog/2010/12/20/android-multithreading-in-a-ui-environment/


15
तो पोस्ट पर एनीमेशन शुरू करना मुख्य धागे पर इसे चलाने से अलग क्यों है, जब वे दोनों अंततः एक ही धागे पर चलते हैं?
गाल

क्योंकि यह एकल थ्रेड मॉडल Android अनुप्रयोगों में खराब प्रदर्शन कर सकता है।
तलहा

1
एनीमेशन न दिखाने से खराब प्रदर्शन का क्या करना है?
गाल

17
मुझे नहीं लगता कि यह प्रश्न का उत्तर देता है, यह शुरुआती लोगों के लिए एक सामान्य उत्तर की तरह है, जो यूआई-थ्रेड और बहु ​​प्रसार के बारे में कुछ भी नहीं जानते हैं। यह इस बात की व्याख्या नहीं करता है कि क्यू में एनीमेशन को आगे फेंकने से एनीमेशन काम करता है; किसी भी पोस्ट () या runOnUiThread () ट्रिक्स का उपयोग किए बिना ui-thread में सीधे निष्पादित करने के लिए एक एनीमेशन माना जाता है।
कैरिज़ो

3
सभी UI कार्य मुख्य थ्रेड (UI थ्रेड) पर होने चाहिए। मुख्य थ्रेड में कॉल के बजाय पोस्ट () का उपयोग करके एनीमेशन का काम करने वाली चाल सही समय है: यदि आप मुख्य धागे में तुरंत कॉल करते हैं, जिसका मतलब है कि आपने "अभी एनीमेशन शुरू करें" बताया है, लेकिन इस समय दृश्य तैयार नहीं है एनीमेशन के लिए (माप, ड्रा ...)। लेकिन अगर आप उस पोस्ट को () में डालते हैं, तो यह कुछ समय के लिए कतार में लंबित शुरू हो जाएगा।
गुयेनडैट

35

क्या यह onCreate या onCreateView पर किया जा रहा है? यदि ऐसा है, तो एप्लिकेशन उस स्थिति में नहीं हो सकता है जहां दृश्य विंडो से जुड़ा हुआ है। व्यू मेट्रिक्स पर आधारित बहुत सारे एल्गोरिदम काम नहीं कर सकते क्योंकि व्यू की माप और स्थिति जैसी चीजों की गणना नहीं की गई है। एंड्रॉइड एनिमेशन में आमतौर पर यूआई गणित के माध्यम से चलने की आवश्यकता होती है

View.post वास्तव में View के संदेश लूप पर एनीमेशन को कतार में रखता है, इसलिए एक बार जब दृश्य खिड़की से जुड़ जाता है, तो यह मैन्युअल रूप से निष्पादित होने के बजाय एनीमेशन को निष्पादित करता है।

आप वास्तव में यूआई थ्रेड पर चीजें चला रहे हैं, लेकिन एक अलग समय पर


स्वीकृत उत्तर भ्रामक है जहां पोस्टर में कहा गया है कि "पोस्ट रननेबल का कारण बनता है (कोड एक अलग धागे में चलाया जाएगा)"। यह सही उत्तर है "आप वास्तव में यूआई थ्रेड पर चीजें चला रहे हैं, लेकिन एक अलग समय पर" - प्लस 1
smitty1

18

अच्छे उत्तर के लिए यहाँ एक नज़र डालें । view.post () हैंडलर.पोस्ट () के समान है। यह मुख्य थ्रेड कतार में चला जाता है और अन्य लंबित कार्यों के समाप्त होने के बाद निष्पादित हो जाता है। यदि आप गतिविधि कहते हैं ।ununUiThread () इसे तुरंत UI थ्रेड पर कॉल किया जाएगा।


31
एक विशाल (और अत्यंत उपयोगी) अंतर जो मैंने पाया है वह view.post () में रननेबल है जब दृश्य पहली बार दिखाया जाएगा। IE, आप इसे भविष्य में किसी बिंदु पर दृश्य की मुद्रास्फीति पर एक एनीमेशन शुरू करने के लिए सेट कर सकते हैं, अंत में इसे दृश्य पदानुक्रम में जोड़ सकते हैं। किस बिंदु पर, तब एनीमेशन निष्पादित होगा और आपको इसके बारे में चिंता करने की आवश्यकता नहीं होगी।
डेव

असल में, हैंडलर.पोस्ट () हमेशा मुख्य थ्रेड पर एक संदेश / रननीय पोस्ट नहीं करता है। यह निर्भर करता है कि हैंडलर कैसे बनाया जाता है (यह एक अलग धागे पर एक लूपर से जुड़ा हो सकता है)। दूसरी ओर, view.post () हमेशा मुख्य धागे पर चलेगा
यार कुकिल्का

4

मुझे लगता है कि समस्या जीवन-चक्र विधि हो सकती है जहां आप पोस्ट () विधि को बुला रहे हैं। क्या आप इसे ऑनक्रिएट () में कर रहे हैं? यदि ऐसा है, तो मुझे गतिविधि के onResume () प्रलेखन में क्या मिला:

फिर से शुरू करने पर()

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

https://developer.android.com/reference/android/app/Activity.html#onResume ()

तो, जैसा कि जो प्लांटे ने कहा, हो सकता है कि आप जिस समय को पोस्ट () कहते हैं, उस समय एनिमेशन शुरू करने के लिए तैयार नहीं हैं, इसलिए इसे onResume () में स्थानांतरित करने का प्रयास करें।

पीडी: वास्तव में यदि आप कोड को onResume () पर स्थानांतरित करते हैं तो मुझे लगता है कि आप पोस्ट () कॉल को हटा सकते हैं क्योंकि आप पहले से ही ui-thread में हैं और दृश्य एनिमेशन शुरू करने के लिए तैयार होना चाहिए।


3
onResumeकई बार कहा जा सकता है (स्क्रीन सो जाता है, गतिविधि को बैकस्टैक पर धकेल दिया जाता है, आदि ...) इसके बाद शुरू में जब "दृश्य तैयार होता है"। अगर कहा जाता है onResume, तो मौसम को ट्रैक करने के लिए एक ध्वज की आवश्यकता हो सकती है, एनीमेशन पहले ही शुरू हो चुका है, कई बार शुरू करने (फिर से) से बचने के लिए।
Samis
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.