Android में हम runOnUiThread का उपयोग कैसे करते हैं?


157

मैं एंड्रॉइड के लिए नया हूं और मैं यूआई-थ्रेड का उपयोग करने की कोशिश कर रहा हूं, इसलिए मैंने एक साधारण परीक्षण गतिविधि लिखी है। लेकिन मुझे लगता है कि मैंने कुछ गलत समझा है, क्योंकि बटन पर क्लिक करने पर - ऐप अब कोई प्रतिक्रिया नहीं देता है

public class TestActivity extends Activity {

    Button btn;
    int i = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btn = (Button)findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                runThread();
            }
        });
    }

    private void runThread(){
        runOnUiThread (new Thread(new Runnable() {  
            public void run() {
                while(i++ < 1000){
                    btn.setText("#"+i);
                    try {
                        Thread.sleep(300);
                    } 
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
             }
        }));
    }
}

जवाबों:


204

नीचे runThreadफंक्शन का स्निपेट सही किया गया है ।

private void runThread() {

    new Thread() {
        public void run() {
            while (i++ < 1000) {
                try {
                    runOnUiThread(new Runnable() {

                        @Override
                        public void run() {
                            btn.setText("#" + i);
                        }
                    });
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }.start();
}

क्या यह लगभग तुरंत एकत्र किया गया कचरा नहीं है? संभवतः आपको थ्रेड ()
निक

14
@ निक: कचरा संग्रहकर्ता देखता है कि स्टैक भी, यानी जब धागा चल रहा हो, तो यह GC'ed नहीं होगा।
मिरो क्रोपसेक

@ विपुल, मेरे पास फोन रोटेशन के बारे में एक सवाल था: मैं चाहता हूं कि एक बार मैं अपने फोन को घुमा दूं यह धागा चलता है और कोई नया धागा नहीं बनता है। क्या आप फोन को घुमाए जाने के बाद नए धागे के निर्माण को रोकने के बारे में कुछ संकेत प्रदान कर सकते हैं?
user1836957

89

बस इसे एक फ़ंक्शन के रूप में लपेटें, फिर अपने बैकग्राउंड थ्रेड से इस फ़ंक्शन को कॉल करें।

public void debugMsg(String msg) {
    final String str = msg;
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mInfo.setText(str);
        }
    });
}

3
यह दिखाने के लिए कि बाहरी दायरे में डेटा का उपयोग कैसे किया जाए ( final)
mariotomo

27

आपके पास यह बैक-टू-फ्रंट है। आपका बटन कॉल करने के लिए परिणाम क्लिक करता है runOnUiThread(), लेकिन इसकी आवश्यकता नहीं है, क्योंकि क्लिक हैंडलर पहले से ही UI थ्रेड पर चल रहा है। फिर, आपका कोड runOnUiThread()एक नया बैकग्राउंड थ्रेड लॉन्च कर रहा है, जहाँ आप UI ऑपरेशन करने की कोशिश करते हैं, जो तब विफल हो जाता है।

इसके बजाय, बस पृष्ठभूमि थ्रेड को अपने क्लिक हैंडलर से सीधे लॉन्च करें। फिर, कॉल को btn.setText()अंदर करने के लिए कॉल को लपेटें runOnUiThread()


हालांकि यह सच है कि क्लिक हैंडलर पहले से ही यूआई थ्रेड में है, एक कॉल runOnUiThread()अनावश्यक है लेकिन यह हानिरहित होना चाहिए। उस विधि के लिए Javadoc कहता है "UI थ्रेड पर निर्दिष्ट क्रिया चलाता है। यदि वर्तमान थ्रेड UI थ्रेड है, तो कार्रवाई तुरंत निष्पादित की जाती है। यदि वर्तमान थ्रेड UI थ्रेड नहीं है, तो कार्रवाई ईवेंट कतार में पोस्ट की गई है UI थ्रेड का। "
k2col


10

RunOnUiThread () का उपयोग करके कई तकनीकें हैं, जो सभी को देखने देती हैं

यह AndroidBasicThreadActivity नामक मेरा मुख्य थ्रेड (UI थ्रेड) है और मैं इसे विभिन्न तरीकों से वर्कर थ्रेड से अपडेट करने जा रहा हूं -

public class AndroidBasicThreadActivity extends AppCompatActivity
{
    public static TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_android_basic_thread);

        textView = (TextView) findViewById(R.id.textview);

        MyAndroidThread myTask = new MyAndroidThread(AndroidBasicThreadActivity.this);
        Thread t1 = new Thread(myTask, "Bajrang");
        t1.start();
    }
}

1.) कार्यकर्ता धागे पर एक तर्क के रूप में गतिविधि के उदाहरण को पारित करके

class MyAndroidThread implements Runnable
{
    Activity activity;
    public MyAndroidThread(Activity activity)
    {
        this.activity = activity;
    }
    @Override
    public void run()
    {

        //perform heavy task here and finally update the UI with result this way - 
        activity.runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
                AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
            }
        });
    }
}

2.) वर्कर थ्रेड में व्यूज पोस्ट (रन करने योग्य रननेबल) विधि का उपयोग करके

class MyAndroidThread implements Runnable
{
    Activity activity;
    public MyAndroidThread(Activity activity)
    {
        this.activity = activity;
    }
    @Override
    public void run()
    {
     //perform heavy task here and finally update the UI with result this way - 
       AndroidBasicThreadActivity.textView.post(new Runnable()
      { 
        @Override
        public void run()
        {
            AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
        }
    });

    }
}

3.) Android.os पैकेज से हैंडलर वर्ग का उपयोग करके अगर हमारे पास संदर्भ नहीं है (यह / getApplicationContext ()) या गतिविधि का उदाहरण (AndroidBasicThreadActivity.this) तो हमें नीचे के रूप में हैंडलर वर्ग का उपयोग करना होगा -

class MyAndroidThread implements Runnable
{
    Activity activity;
    public MyAndroidThread(Activity activity)
    {
        this.activity = activity;
    }
    @Override
   public void run()
  {
  //perform heavy task here and finally update the UI with result this way - 
  new Handler(Looper.getMainLooper()).post(new Runnable() {
        public void run() {
            AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
        }
    });
  }
}

धन्यवाद .. गतिविधि के रनऑउट के बारे में दोहराने के बजाय, आपने इसे लागू करने के सभी संभावित तरीकों का उल्लेख किया है ..
arun

धन्यवाद .. गतिविधि के रनऑउट के बारे में दोहराने के बजाय, आपने इसे लागू करने के सभी संभावित तरीकों का उल्लेख किया है ..
arun

6

अगर टुकड़े में उपयोग कर रहे हैं तो बस लिखें

getActivity().runOnUiThread(new Runnable() {
    @Override
    public void run() {
        // Do something on UiThread
    }
});

1

तुम्हारा यह:

@UiThread
    public void logMsg(final String msg) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                Log.d("UI thread", "I am the UI thread");


            }
        });
    }

1

हम ऐप्स को स्मूथ बनाने और ANR से बचने के लिए वर्कर थ्रेड का उपयोग करते हैं। वर्कर ट्रेड में भारी प्रक्रिया के बाद हमें UI अपडेट करना पड़ सकता है। यूआई को केवल यूआई थ्रेड से अपडेट किया जा सकता है। ऐसे मामलों में, हम हैंडलर का उपयोग करते हैं या runOnUiTread दोनों में एक Runnable रन विधि है जो UI थ्रेड में निष्पादित होती है। OnClick विधि UI थ्रेड में चलती है इसलिए यहां runOnUiThread का उपयोग करने की आवश्यकता नहीं है।

कोटलिन का उपयोग करना

गतिविधि में रहते हुए,

this.runOnUiThread {
      // Do stuff
}

फ्रैगमेंट से,

activity?.runOnUiThread {
      // Do stuff
}

जावा का उपयोग करना ,

this.runOnUiThread(new Runnable() {
     void run() {
         // Do stuff
     }
});

0

आप इस नमूने से उपयोग कर सकते हैं:

निम्नलिखित उदाहरण में, हम इस सुविधा का उपयोग करने के लिए एक पर्याय खोज से परिणाम प्रकाशित करने जा रहे हैं जो एक पृष्ठभूमि थ्रेड द्वारा संसाधित किया गया था।

OnCreate गतिविधि कॉलबैक के दौरान लक्ष्य को पूरा करने के लिए, हम एक निर्मित थ्रेड पर searchTask चलाने के लिए onClickListener की स्थापना करेंगे।

जब उपयोगकर्ता खोज बटन पर क्लिक करता है, तो हम एक Runnable अनाम वर्ग बनाएंगे जो R.id.wordEt EditText में टाइप किए गए शब्द को खोजता है और Runnable को निष्पादित करने के लिए थ्रेड प्रारंभ करता है।

जब खोज पूरी हो जाती है, तो हम परिणाम को प्रकाशित करने के लिए Runnable SetSynonymResult का एक उदाहरण बनाएंगे, जो UI थ्रेड पर पर्याय TextView पर वापस प्रकाशित करेगा।

यह तकनीक कुछ समय के लिए सबसे सुविधाजनक नहीं है, खासकर जब हमारे पास गतिविधि की पहुंच नहीं है; इसलिए, निम्नलिखित अध्यायों में, हम पृष्ठभूमि कंप्यूटिंग कार्य से UI को अद्यतन करने के लिए सरल और क्लीनर तकनीकों पर चर्चा करने जा रहे हैं।

public class MainActivity extends AppCompatActivity {

    class SetSynonymResult implements Runnable {
        String synonym;

        SetSynonymResult(String synonym) {
            this.synonym = synonym;
        }

        public void run() {
            Log.d("AsyncAndroid", String.format("Sending synonym result %s on %d",
                    synonym, Thread.currentThread().getId()) + " !");
            TextView tv = (TextView) findViewById(R.id.synonymTv);
            tv.setText(this.synonym);
        }
    }

    ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button search = (Button) findViewById(R.id.searchBut);
        final EditText word = (EditText) findViewById(R.id.wordEt);
        search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Runnable searchTask = new Runnable() {
                    @Override
                    public void run() {
                        String result = searchSynomim(word.getText().toString());
                        Log.d("AsyncAndroid", String.format("Searching for synonym for %s on %s",
                                word.getText(), Thread.currentThread().getName()));
                        runOnUiThread(new SetSynonymResult(result));
                    }
                };
                Thread thread = new Thread(searchTask);
                thread.start();
            }
        });

    }

    static int i = 0;

    String searchSynomim(String word) {
        return ++i % 2 == 0 ? "fake" : "mock";
    }
}

स्रोत :

अतुल्यकालिक Android प्रोग्रामिंग हेलर Vasconcelos



0
  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        gifImageView = (GifImageView) findViewById(R.id.GifImageView);
        gifImageView.setGifImageResource(R.drawable.success1);

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //dummy delay for 2 second
                    Thread.sleep(8000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //update ui on UI thread
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        gifImageView.setGifImageResource(R.drawable.success);
                    }
                });

            }
        }).start();

    }

0

इसे इस्तेमाल करे: getActivity().runOnUiThread(new Runnable...

ये इसलिए:

1) इसे चलाने के लिए अपने कॉल में निहित है, क्योंकि यह AsyncTask की बात कर रहा है , आपके टुकड़े का नहीं।

2) टुकड़े में runOnUiThread नहीं है।

हालांकि, गतिविधि करता है।

ध्यान दें कि यदि आप पहले से ही मुख्य थ्रेड पर हैं, तो गतिविधि केवल रननीय को निष्पादित करती है, अन्यथा यह एक हैंडलर का उपयोग करती है। यदि आप इस संदर्भ के बारे में चिंता नहीं करना चाहते हैं, तो आप अपने टुकड़े में हैंडलर लागू कर सकते हैं, यह वास्तव में बहुत आसान है:

// एक वर्ग उदाहरण

private Handler mHandler = new Handler(Looper.getMainLooper());

// आपके कोड में कहीं और

mHandler.post(<your runnable>);

// ^ यह हमेशा मुख्य धागे पर अगले रन लूप पर चलाया जाएगा।

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