অন্য থ্রেড থেকে মূল থ্রেডে চলমান কোড


326

একটি অ্যান্ড্রয়েড পরিষেবাতে আমি কিছু পটভূমি কাজ করার জন্য থ্রেড তৈরি করেছি।

আমার এমন একটি পরিস্থিতি রয়েছে যেখানে মূল থ্রেডের বার্তার কাতারে একটি থ্রেডকে নির্দিষ্ট কাজ পোস্ট করা দরকার, উদাহরণস্বরূপ এ Runnable

একটি উপায় আছে পেতে হয় Handlerমূল থ্রেড এবং পোস্টের Message/ Runnableআমার অন্যান্য থ্রেড থেকে এটা কিভাবে?

ধন্যবাদ,


2
আপনি কাস্টম ব্রডকাস্ট রিসিভারটিও ব্যবহার করতে পারেন .... আমার উত্তরটি এখানে চেষ্টা করুন, [ইনার ব্রডকাস্ট রিসিভার] [1] [1]: স্ট্যাকওভারফ্লো.com
মেলবোর্ন লোপস

অনেক উপায় আছে। ডেভিডের উত্তর ছাড়াও এবং তার উত্তরে ডেজিকেইর মন্তব্য ছাড়াও (3) আপনি ব্রডকাস্ট রিসিভার ব্যবহার করতে পারেন, বা (4) পরিষেবা শুরু করতে ব্যবহৃত ইনট্যান্টের অতিরিক্তগুলিতে হ্যান্ডলারটি পাস করতে পারেন, এবং তারপরে getIntant ব্যবহার করে মূল থ্রেডের হ্যান্ডলারটি পুনরুদ্ধার করতে পারেন ( ) .getExtras ()।
অশোক বিজয় দেবনাথ

2
@ সাজ্জাদ-হিসসাইন খান, ২০১২ সাল থেকে এই প্রশ্নটি কোটলিন ট্যাগের সাথে জাভাতে বেশিরভাগ উত্তর দিয়ে কেন ট্যাগ করবেন?
টেনফোর04

উত্তর:


617

দ্রষ্টব্য: এই উত্তরটি এত বেশি মনোযোগ পেয়েছে যে আমার এটি আপডেট করা দরকার। আসল উত্তর পোস্ট হওয়ার পরে, @ ডিজাইকি মন্তব্যটি মূল উত্তরটির মতো প্রায় মনোযোগ পেয়েছে। সুতরাং এখানে 2 সম্ভাব্য সমাধান রয়েছে:

1. যদি আপনার পটভূমির থ্রেডে কোনও Contextঅবজেক্টের রেফারেন্স থাকে:

আপনার ব্যাকগ্রাউন্ড কর্মী থ্রেডগুলিতে একটি প্রসঙ্গ অবজেক্টে অ্যাক্সেস রয়েছে তা নিশ্চিত করুন (অ্যাপ্লিকেশন প্রসঙ্গ বা পরিষেবার প্রসঙ্গ হতে পারে)। তারপরে ব্যাকগ্রাউন্ড কর্মী থ্রেডে এটি করুন:

// Get a handler that can be used to post to the main thread
Handler mainHandler = new Handler(context.getMainLooper());

Runnable myRunnable = new Runnable() {
    @Override 
    public void run() {....} // This is your code
};
mainHandler.post(myRunnable);

২. যদি আপনার পটভূমির থ্রেডে কোনও Contextঅবজেক্ট (বা প্রয়োজন) না থাকে

(@dzeikei দ্বারা প্রস্তাবিত):

// Get a handler that can be used to post to the main thread
Handler mainHandler = new Handler(Looper.getMainLooper());

Runnable myRunnable = new Runnable() {
    @Override 
    public void run() {....} // This is your code
};
mainHandler.post(myRunnable);

1
ধন্যবাদ ডেভিড এটি আমার পক্ষে কাজ করেছে, আপনি যদি আমাকে সাহায্য করতে পারেন তবে আরও একটি জিনিস, যদি আমি হ্যান্ডলারটি প্রসারিত করি এবং হ্যান্ডেল ম্যাসেজ () প্রেরণ করি তবে এটি কী মূল বার্তাটি পরিচালনা করতে বাধা দেয়? এটি কৌতুহলের বাইরে থাকা একটি প্রশ্ন ..
আহমেদ

2
না sub আপনি যদি সাবক্লাস Handler(বা Handler.Callbackইন্টারফেস ব্যবহার করেন ) আপনার handleMessage()পদ্ধতিটি কেবলমাত্র আপনার বার্তা হ্যান্ডলারের সাহায্যে পোস্ট করা বার্তাগুলির জন্য ডাকা হবে। মূল থ্রেড বার্তা পোস্ট / প্রক্রিয়া করতে আলাদা হ্যান্ডলার ব্যবহার করছে যাতে কোনও বিরোধ নেই।
ডেভিড ওয়াসার

205
আমি বিশ্বাস করি আপনি যদি ব্যবহার করেন তবে আপনার প্রসঙ্গের প্রয়োজনও হবে নাHandler mainHandler = new Handler(Looper.getMainLooper());
dzeikei

6
মাইনর পয়েন্ট; আপনার কোডটি যেখানে নেই ... বর্তমানে রয়েছে। এটি হওয়া উচিতnew Runnable(){@Override public void run() {....}};
রিচার্ড টিংল

1
@ সাগরদেভঙ্গা এটি ভিন্ন প্রশ্ন জিজ্ঞাসা করার সঠিক জায়গা নয়। দয়া করে একটি নতুন প্রশ্ন পোস্ট করুন, কোনও সম্পর্কযুক্ত উত্তরের মন্তব্য নয়। আপনি সেভাবে আরও ভাল এবং দ্রুত প্রতিক্রিয়া পাবেন।
ডেভিড ওয়াসার

138

সঠিকভাবে নির্দেশিত নীচে একজন মন্তব্যকারী হিসাবে, এটি পরিষেবার জন্য সাধারণ সমাধান নয়, কেবল আপনার ক্রিয়াকলাপ থেকে চালিত থ্রেডগুলির জন্য (কোনও পরিষেবা এমন থ্রেড হতে পারে, তবে সেগুলি সমস্ত নয়)। পরিষেবাদি-ক্রিয়াকলাপের যোগাযোগের জটিল বিষয়ে দয়া করে অফিসিয়াল ডকটির পুরো পরিষেবাদি বিভাগটি পড়ুন - এটি জটিল, সুতরাং এটি বেসিকগুলি বোঝার জন্য অর্থ প্রদান করবে: http://developer.android.com/guide/compferences/services.html #Notifications

নীচের পদ্ধতিটি সহজতম ক্ষেত্রে কাজ করতে পারে।

যদি আমি আপনাকে সঠিকভাবে বুঝতে পারি তবে আপনাকে অ্যাপ্লিকেশনটির জিইউআই থ্রেডে এক্সিকিউট করার জন্য কিছু কোডের প্রয়োজন ("মূল" থ্রেড বলে অন্য কোনও কিছু সম্পর্কে ভাবতে পারে না)। এর জন্য এখানে একটি পদ্ধতি রয়েছে Activity:

someActivity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
           //Your code to run in GUI thread here
        }//public void run() {
});

দস্তাবেজ: http://developer.android.com/references/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29

আশা করি এটিই আপনি খুঁজছেন।


20
ওপি বলেছে যে সে এ থ্রেড চালাচ্ছে Service। আপনি runOnUiThread()একটি ব্যবহার করতে পারবেন না Service। এই উত্তরটি বিভ্রান্তিমূলক এবং জিজ্ঞাসিত প্রশ্নের সমাধান করে না।
ডেভিড ওয়াসার

31

আর একটি সহজ উপায় আছে, যদি আপনার প্রসঙ্গে অ্যাক্সেস না থাকে।

1)। প্রধান লুপ থেকে একটি হ্যান্ডলার তৈরি করুন:

Handler uiHandler = new Handler(Looper.getMainLooper());

2)। একটি চলমান ইন্টারফেস প্রয়োগ করুন:

Runnable runnable = new Runnable() { // your code here }

3)। UIHandler এ আপনার চলমান পোস্ট করুন:

uiHandler.post(runnable);

এগুলি সব ;-) থ্রেড সহ মজা করুন তবে সেগুলি সিঙ্ক্রোনাইজ করতে ভুলবেন না।


29

যদি আপনি কোনও থ্রেডে কোড চালনা করেন, উদাহরণস্বরূপ কিছু ক্রিয়াকলাপে বিলম্ব করুন, তবে আপনাকে runOnUiThreadপ্রসঙ্গ থেকে অনুরোধ করতে হবে। উদাহরণস্বরূপ, যদি আপনার কোড MainActivityশ্রেণীর ভিতরে থাকে তবে এটি ব্যবহার করুন:

MainActivity.this.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        myAction();
    }
});

যদি আপনার পদ্ধতিটি প্রধান (ইউআই থ্রেড) থেকে বা অন্য থ্রেড থেকে আহ্বান করা যেতে পারে তবে আপনার যেমন একটি চেক প্রয়োজন:

public void myMethod() {
   if( Looper.myLooper() == Looper.getMainLooper() ) {
       myAction();
   }
   else {

}

7
ওপি বলেছে যে সে এ থ্রেড চালাচ্ছে Service। আপনি runOnUiThread()একটি ব্যবহার করতে পারবেন না Service
ডেভিড ওয়াসার

@ ডেভিডওয়াসার এটি কোথাও নথিভুক্ত আছে? পদ্ধতি ডক্স এ সম্পর্কে কিছু উল্লেখ করে না। বিকাশকারী.অ্যান্ড্রয়েড.
গ্রেগ ব্রাউন

1
@ গ্রেগব্রাউন যেমন আপনি Activityডকুমেন্টেশনের লিঙ্কটি দ্বারা নির্দেশ করেছেন , runOnUiThread()এটি একটি পদ্ধতি Activity। এটি কোনও পদ্ধতি নয় Service, সুতরাং আপনি এটি ব্যবহার করতে পারবেন না। এর থেকে পরিষ্কার আর কী হতে পারে?
ডেভিড ওয়াসার 4'16

@ ডেভিডওয়াসার মেলা যথেষ্ট। আমি কেন এখনও প্রশ্নটি জিজ্ঞাসা করেছি তা মনে নেই (এটি প্রায় এক বছর আগে পোস্ট করা হয়েছিল)।
গ্রেগ ব্রাউন

24

একটি ঘনীভূত কোড ব্লকটি নিম্নরূপ:

   new Handler(Looper.getMainLooper()).post(new Runnable() {
       @Override
       public void run() {
           // things to do on the main thread
       }
   });

এর মধ্যে ক্রিয়াকলাপ রেফারেন্স বা অ্যাপ্লিকেশন রেফারেন্সটি অন্তর্ভুক্ত করা জড়িত না।

কোটলিন সমতুল্য:

    Handler(Looper.getMainLooper()).post(Runnable {
        // things to do on the main thread
    })

20

কোটলিন সংস্করণ

আপনি যখন কোনও ক্রিয়াকলাপে থাকেন , তখন ব্যবহার করুন

runOnUiThread {
    //code that runs in main
}

আপনার যখন ক্রিয়াকলাপের প্রসঙ্গ থাকে , তখন mContext ব্যবহার করুন

mContext.runOnUiThread {
    //code that runs in main
}

আপনি যখন কোথাও রয়েছেন যেখানে কোনও প্রসঙ্গ উপলব্ধ নেই , তখন ব্যবহার করুন

Handler(Looper.getMainLooper()).post {  
    //code that runs in main
}

এটি কোটলিনের কোন সংস্করণ তা নিশ্চিত নয়, তবে আমাকে ধনুর্বন্ধনী যুক্ত করতে হয়েছিল:runOnUiThread(){...}
ওয়েক্স

5

সবচেয়ে সহজ উপায় বিশেষত আপনার যদি প্রসঙ্গ না থাকে আপনি যদি RxAndroid ব্যবহার করেন তবে আপনি এটি করতে পারেন:

AndroidSchedulers.mainThread().scheduleDirect {
    runCodeHere()
}


4

একটি পদ্ধতি যা আমি ভাবতে পারি তা হ'ল:

1) UI পরিষেবাতে বাঁধতে দিন।
2) নীচের মত একটি পদ্ধতি Binderযা আপনার নিবন্ধভুক্ত দ্বারা প্রকাশ করুন Handler:

public void registerHandler(Handler handler) {
    mHandler = handler;
}

3) ইউআই থ্রেডে, পরিষেবার সাথে আবদ্ধ হওয়ার পরে উপরের পদ্ধতিটি কল করুন:

mBinder.registerHandler(new Handler());

৪) আপনার কার্য পোস্ট করার জন্য পরিষেবার থ্রেডে হ্যান্ডলারটি ব্যবহার করুন:

mHandler.post(runnable);

3

HandlerThread অ্যান্ড্রয়েডে স্বাভাবিক জাভা থ্রেডসের আরও ভাল বিকল্প।

  1. একটি হ্যান্ডলারথ্রেড তৈরি করুন এবং এটি শুরু করুন
  2. হ্যান্ডলারথ্রেড থেকে লুপার সহ একটি হ্যান্ডলার তৈরি করুন :requestHandler
  3. postএকটি RunnableকাজrequestHandler

ইউআই থ্রেড থেকে যোগাযোগ HandlerThread

  1. মূল থ্রেড Handlerসহ একটি তৈরি করুন Looper: responseHandlerএবং ওভাররাইড handleMessageপদ্ধতি
  2. Runnableঅন্যান্য থ্রেডের ভিতরে টাস্ক ( HandlerThreadএই ক্ষেত্রে), কল sendMessageকরুনresponseHandler
  3. এই sendMessageফল আবাহন handleMessageমধ্যে responseHandler
  4. থেকে বৈশিষ্ট্যগুলি পান Messageএবং এটি প্রক্রিয়া করুন, ইউআই আপডেট করুন

উদাহরণ : TextViewএকটি ওয়েব পরিষেবা থেকে প্রাপ্ত ডেটা সহ আপডেট করুন । যেহেতু HandlerThreadনেটওয়ার্ক অপারেশনের জন্য তৈরি নন-ইউআই থ্রেডে ওয়েব পরিষেবা চালু করা উচিত । আপনি ওয়েব পরিষেবা থেকে সামগ্রীটি পেয়ে গেলে আপনার মূল থ্রেড (ইউআই থ্রেড) হ্যান্ডলারে Handlerবার্তা প্রেরণ করুন এবং এটি বার্তাটি পরিচালনা করবে এবং ইউআই আপডেট করবে।

কোডের উদাহরণ:

HandlerThread handlerThread = new HandlerThread("NetworkOperation");
handlerThread.start();
Handler requestHandler = new Handler(handlerThread.getLooper());

final Handler responseHandler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message msg) {
        txtView.setText((String) msg.obj);
    }
};

Runnable myRunnable = new Runnable() {
    @Override
    public void run() {
        try {
            Log.d("Runnable", "Before IO call");
            URL page = new URL("http://www.your_web_site.com/fetchData.jsp");
            StringBuffer text = new StringBuffer();
            HttpURLConnection conn = (HttpURLConnection) page.openConnection();
            conn.connect();
            InputStreamReader in = new InputStreamReader((InputStream) conn.getContent());
            BufferedReader buff = new BufferedReader(in);
            String line;
            while ((line = buff.readLine()) != null) {
                text.append(line + "\n");
            }
            Log.d("Runnable", "After IO call:"+ text.toString());
            Message msg = new Message();
            msg.obj = text.toString();
            responseHandler.sendMessage(msg);


        } catch (Exception err) {
            err.printStackTrace();
        }
    }
};
requestHandler.post(myRunnable);

দরকারী নিবন্ধ:

handlerthreads-এবং-কেন-আপনি-উচিত-করা-ব্যবহার-তাদের-ইন-আপনার-অ্যান্ড্রয়েড-অ্যাপ্লিকেশান

অ্যান্ড্রয়েড-looper-হ্যান্ডলার-handlerthread-ই


2

আমি জানি এটি একটি পুরানো প্রশ্ন, তবে আমি কোটলিন এবং জাভা উভয় ক্ষেত্রেই একটি মূল থ্রেড ওয়ান-লাইন পেয়েছি। এটি কোনও পরিষেবার জন্য সেরা সমাধান নাও হতে পারে, তবে এমন কিছু কল করার জন্য যা কোনও খণ্ডের ইউআইকে পরিবর্তন করবে এটি অত্যন্ত সহজ এবং স্পষ্ট।

জাভা (8):

 getActivity().runOnUiThread(()->{
      //your main thread code
 });

Kotlin:

this.runOnUiThread {
     //your main thread code
}

1

এই পদ্ধতি অনুসরণ করুন। এইভাবে ব্যবহার করে আপনি ব্যাকগ্রাউন্ড থ্রেড থেকে কেবল ইউআই আপডেট করতে পারবেন। মূল (UI) থ্রেডে রানঅনুআইথ্রেড কাজ। আমি মনে করি এই কোড স্নিপেট কম জটিল এবং সহজ, বিশেষত নবজাতকদের জন্য।

AsyncTask.execute(new Runnable() {
            @Override
            public void run() {

            //code you want to run on the background
            someCode();

           //the code you want to run on main thread
 MainActivity.this.runOnUiThread(new Runnable() {

                    public void run() {

/*the code you want to run after the background operation otherwise they will executed earlier and give you an error*/
                        executeAfterOperation();

                   }
                });
            }
        });

একটি পরিষেবা ক্ষেত্রে

oncreate একটি হ্যান্ডলার তৈরি করুন

 handler = new Handler();

তারপরে এটি ব্যবহার করুন

 private void runOnUiThread(Runnable runnable) {
        handler.post(runnable);
    }

এই কোড স্নিপেটের জন্য আপনাকে ধন্যবাদ, যা কিছু সীমিত, তাত্ক্ষণিক সহায়তা সরবরাহ করতে পারে। একটি সঠিক ব্যাখ্যা কেন এটি সমস্যার একটি ভাল সমাধান তা দেখিয়ে তার দীর্ঘমেয়াদী মানকে ব্যাপকভাবে উন্নত করবে এবং ভবিষ্যতে পাঠকদের আরও অন্যান্য অনুরূপ প্রশ্নের সাথে আরও দরকারী করে তুলবে। আপনার অনুমানগুলি সহ কিছু ব্যাখ্যা যুক্ত করতে দয়া করে আপনার উত্তরটি সম্পাদনা করুন।
iBug


1

সুতরাং সর্বাধিক সুবিধাজনক বাছাই করা হয়:

import android.os.AsyncTask
import android.os.Handler
import android.os.Looper

object Dispatch {
    fun asyncOnBackground(call: ()->Unit) {
        AsyncTask.execute {
            call()
        }
    }

    fun asyncOnMain(call: ()->Unit) {
        Handler(Looper.getMainLooper()).post {
            call()
        }
    }
}

এবং তারপর:

Dispatch.asyncOnBackground {
    val value = ...// super processing
    Dispatch.asyncOnMain { completion(value)}
}

0
public void mainWork() {
    new Handler(Looper.getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            //Add Your Code Here
        }
    });
}

এটি কোনও সমস্যা ছাড়াই কোনও পরিষেবা শ্রেণিতেও কাজ করতে পারে।


যদিও এই কোডটি প্রশ্নের উত্তর দিতে পারে আপনি এখনও কয়েকটি ব্যাখ্যামূলক বাক্য যুক্ত করার বিষয়টি বিবেচনা করতে পারেন কারণ এটি অন্যান্য ব্যবহারকারীর জন্য আপনার উত্তরটির মান বাড়িয়ে তোলে!
এমবিটি

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.