অ্যান্ড্রয়েড "কেবলমাত্র মূল থ্রেড যা একটি ভিউ হায়ারার্কি তৈরি করেছে তার দর্শনগুলিকে স্পর্শ করতে পারে।"


938

আমি অ্যান্ড্রয়েডে একটি সাধারণ সঙ্গীত প্লেয়ার তৈরি করেছি। প্রতিটি গানের দর্শনটিতে একটি সিকবার রয়েছে, এটি এভাবে প্রয়োগ করা হয়েছে:

public class Song extends Activity implements OnClickListener,Runnable {
    private SeekBar progress;
    private MediaPlayer mp;

    // ...

    private ServiceConnection onService = new ServiceConnection() {
          public void onServiceConnected(ComponentName className,
            IBinder rawBinder) {
              appService = ((MPService.LocalBinder)rawBinder).getService(); // service that handles the MediaPlayer
              progress.setVisibility(SeekBar.VISIBLE);
              progress.setProgress(0);
              mp = appService.getMP();
              appService.playSong(title);
              progress.setMax(mp.getDuration());
              new Thread(Song.this).start();
          }
          public void onServiceDisconnected(ComponentName classname) {
              appService = null;
          }
    };

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.song);

        // ...

        progress = (SeekBar) findViewById(R.id.progress);

        // ...
    }

    public void run() {
    int pos = 0;
    int total = mp.getDuration();
    while (mp != null && pos<total) {
        try {
            Thread.sleep(1000);
            pos = appService.getSongPosition();
        } catch (InterruptedException e) {
            return;
        } catch (Exception e) {
            return;
        }
        progress.setProgress(pos);
    }
}

এটি কাজ করে। এখন আমি একটি টাইমার গানের অগ্রগতি সেকেন্ড / মিনিট গণনা করতে চান। তাই আমি একটি করা TextViewলেআউট সঙ্গে এটি পেতে findViewById()মধ্যে onCreate(), এবং এই করা run()পর progress.setProgress(pos):

String time = String.format("%d:%d",
            TimeUnit.MILLISECONDS.toMinutes(pos),
            TimeUnit.MILLISECONDS.toSeconds(pos),
            TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(
                    pos))
            );
currentTime.setText(time);  // currentTime = (TextView) findViewById(R.id.current_time);

তবে সেই শেষ লাইনটি আমাকে ব্যতিক্রম দেয়:

android.view.ViewRoot $ CalledFromWrongThreadException: কেবলমাত্র মূল থ্রেড যা একটি ভিউ হায়ারার্কি তৈরি করেছে কেবল তার দর্শনগুলিকে স্পর্শ করতে পারে।

তবুও আমি এখানে মূলত একই জিনিসটি করছি SeekBar- যেমনটি তৈরি করছি - ভিউ তৈরি করা onCreate, তারপরে স্পর্শ করা run()- এবং এটি আমাকে এই অভিযোগ দেয় না।

উত্তর:


1893

আপনাকে ব্যাকগ্রাউন্ড টাস্কের অংশটি সরিয়ে নিতে হবে যা ইউআই আপডেট করে মূল থ্রেডে। এর জন্য কোডের একটি সহজ টুকরা রয়েছে:

runOnUiThread(new Runnable() {

    @Override
    public void run() {

        // Stuff that updates the UI

    }
});

জন্য ডকুমেন্টেশন Activity.runOnUiThread

ব্যাকগ্রাউন্ডে চলমান পদ্ধতিটির ভিতরে এটি কেবল নীড় করে, এবং তারপরে কোডটির অনুলিপি করুন যা ব্লকের মাঝখানে কোনও আপডেট প্রয়োগ করে। সম্ভব মাত্র কয়েকটি ক্ষুদ্রতম কোড অন্তর্ভুক্ত করুন, অন্যথায় আপনি ব্যাকগ্রাউন্ড থ্রেডের উদ্দেশ্যকে পরাস্ত করতে শুরু করেন।


5
একটি কবজ মত কাজ। আমার এখানে কেবল সমস্যাটি হ'ল আমি error.setText(res.toString());রান () পদ্ধতির অভ্যন্তরে একটি কাজ করতে চেয়েছিলাম , তবে আমি
রেজিসটি

64
এ সম্পর্কে একটি সংক্ষিপ্ত মন্তব্য আমার একটি পৃথক থ্রেড ছিল যা ইউআই সংশোধন করার চেষ্টা করছিল এবং উপরের কোডটি কাজ করেছিল, তবে আমার ক্রিয়াকলাপ অবজেক্ট থেকে রানঅনউইথ্রেড কল হয়েছিল। আমি ভালো কিছু কি ছিল myActivityObject.runOnUiThread(etc)
কারবি

1
@ কিরবি এই রেফারেন্সের জন্য আপনাকে ধন্যবাদ। আপনি কেবল 'MainActivity.this' করতে পারেন এবং এটির পাশাপাশি কাজ করা উচিত যাতে আপনার ক্রিয়াকলাপ শ্রেণীর রেফারেন্স রাখতে হয় না।
জেরোমেরো

24
এটি runOnUiThread()ক্রিয়াকলাপের একটি পদ্ধতি এটি নির্ধারণ করতে আমার কিছুটা সময় লেগেছে । আমি আমার কোডটি একটি খণ্ডে চালাচ্ছিলাম। আমি কাজ শেষ করেছিলাম getActivity().runOnUiThread(etc)এবং এটি কাজ করে। ফ্যান্টাস্টিক !;
লেজোনল

'রানঅনুআইথ্রেড' পদ্ধতির শরীরে লেখা কাজটি কি আমরা থামিয়ে দিতে পারি?
করণ শর্মা

143

আমি এটি runOnUiThread( new Runnable(){ ..ভিতরে রেখে সমাধান করেছি run():

thread = new Thread(){
        @Override
        public void run() {
            try {
                synchronized (this) {
                    wait(5000);

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            dbloadingInfo.setVisibility(View.VISIBLE);
                            bar.setVisibility(View.INVISIBLE);
                            loadingText.setVisibility(View.INVISIBLE);
                        }
                    });

                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Intent mainActivity = new Intent(getApplicationContext(),MainActivity.class);
            startActivity(mainActivity);
        };
    };  
    thread.start();

2
এই এক দোলা। তথ্যের জন্য ধন্যবাদ যে এটি অন্য যে কোনও থ্রেডের অভ্যন্তরেও ব্যবহার করা যেতে পারে।
নবীন

আপনাকে ধন্যবাদ, ইউআই থ্রেডে ফিরে যেতে একটি থ্রেড তৈরি করা সত্যিই দুঃখজনক তবে কেবল এই সমাধানটি আমার কেসটি বাঁচিয়েছে।
পিয়েরে মাউই

2
একটি গুরুত্বপূর্ণ বিষয় হ'ল wait(5000);এটি রান্নেবলের অভ্যন্তরে নেই, অন্যথায় আপনার ইউআইটি অপেক্ষা করার সময়কালে স্থির হয়ে যাবে। AsyncTaskএগুলির মতো ক্রিয়াকলাপের জন্য আপনার থ্রেডের পরিবর্তে ব্যবহার করা উচিত ।
মার্টিন

এটি মেমরি ফুটোটির জন্য খুব খারাপ
রাফেল লিমা

কেন সিঙ্ক্রোনাইজড ব্লক নিয়ে বিরক্ত করবেন? এর অভ্যন্তরীণ কোডটি যুক্তিসঙ্গতভাবে থ্রেড নিরাপদ দেখাচ্ছে (যদিও আমি আমার শব্দগুলি খেতে সম্পূর্ণ প্রস্তুত)।
ডেভিড

69

এর আমার সমাধান:

private void setText(final TextView text,final String value){
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            text.setText(value);
        }
    });
}

একটি পটভূমি থ্রেড এ পদ্ধতি কল করুন।


ত্রুটি: (, 73,) 67) ত্রুটি: অ স্থির পদ্ধতি সেট (স্ট্রিং) কোনও স্থির প্রসঙ্গ থেকে উল্লেখ করা যায় না

1
আমার পরীক্ষার ক্লাসগুলিতে আমার একই সমস্যা আছে। এটি আমার জন্য কবজির মতো কাজ করেছিল। তবে, এর সাথে প্রতিস্থাপন runOnUiThreadকরা হচ্ছে runTestOnUiThread। ধন্যবাদ
ড্যাডিমো

28

সাধারণত, ব্যবহারকারীর ইন্টারফেসের সাথে জড়িত যে কোনও ক্রিয়া মূল বা ইউআই থ্রেডে করতে হবে, এটিই onCreate()এবং ইভেন্ট হ্যান্ডলিং সম্পাদিত হয়। এটির নিশ্চিত হওয়ার একটি উপায় হ'ল রানঅনউইথ্রেড () ব্যবহার করা হচ্ছে, অন্যটি হ্যান্ডলার ব্যবহার করছে।

ProgressBar.setProgress() এর একটি ব্যবস্থা আছে যার জন্য এটি সর্বদা মূল থ্রেডে চালিত হবে, সুতরাং সে কারণেই এটি কাজ করেছিল।

ব্যথাহীন থ্রেডিং দেখুন ।


যে লিঙ্ক-এ যন্ত্রণাহীন থ্রেডিং নিবন্ধ এখন একটি 404. এখানে একটি (পুরনো?) ব্লগে যন্ত্রণাহীন থ্রেড করা টুকরা একটি লিঙ্ক - android-developers.blogspot.com/2009/05/painless-threading.html
টনি অ্যাডামস

20

আমি এই পরিস্থিতিতে ছিলাম, তবে আমি হ্যান্ডলার অবজেক্টের সাথে একটি সমাধান পেয়েছি।

আমার ক্ষেত্রে, আমি পর্যবেক্ষক প্যাটার্ন সহ একটি অগ্রগতি ডায়ালগ আপডেট করতে চাই । আমার দর্শন পর্যবেক্ষককে প্রয়োগ করে এবং আপডেট পদ্ধতিটিকে ওভাররাইড করে।

সুতরাং, আমার মূল থ্রেডটি ভিউ তৈরি করে এবং অন্য একটি থ্রেড আপডেট পদ্ধতিটি কল করে যা প্রগ্রেসডায়ালপ আপডেট করে এবং ....:

শুধুমাত্র আসল থ্রেড যা একটি ভিউ হায়ারার্কি তৈরি করেছে তার দর্শনগুলিকে স্পর্শ করতে পারে।

হ্যান্ডলার অবজেক্ট দিয়ে সমস্যাটি সমাধান করা সম্ভব।

নীচে, আমার কোডের বিভিন্ন অংশ:

public class ViewExecution extends Activity implements Observer{

    static final int PROGRESS_DIALOG = 0;
    ProgressDialog progressDialog;
    int currentNumber;

    public void onCreate(Bundle savedInstanceState) {

        currentNumber = 0;
        final Button launchPolicyButton =  ((Button) this.findViewById(R.id.launchButton));
        launchPolicyButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                showDialog(PROGRESS_DIALOG);
            }
        });
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        switch(id) {
        case PROGRESS_DIALOG:
            progressDialog = new ProgressDialog(this);
            progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            progressDialog.setMessage("Loading");
            progressDialog.setCancelable(true);
            return progressDialog;
        default:
            return null;
        }
    }

    @Override
    protected void onPrepareDialog(int id, Dialog dialog) {
        switch(id) {
        case PROGRESS_DIALOG:
            progressDialog.setProgress(0);
        }

    }

    // Define the Handler that receives messages from the thread and update the progress
    final Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            int current = msg.arg1;
            progressDialog.setProgress(current);
            if (current >= 100){
                removeDialog (PROGRESS_DIALOG);
            }
        }
    };

    // The method called by the observer (the second thread)
    @Override
    public void update(Observable obs, Object arg1) {

        Message msg = handler.obtainMessage();
        msg.arg1 = ++currentPluginNumber;
        handler.sendMessage(msg);
    }
}

এই ব্যাখ্যাটি এই পৃষ্ঠায় পাওয়া যাবে এবং আপনাকে অবশ্যই "দ্বিতীয় থ্রেডের সাথে উদাহরণস্বরূপ অগ্রগতি ডায়ালগ" পড়তে হবে।


10

আপনি প্রধান ইউআই থ্রেডকে বিরক্ত না করে ভিউ মুছতে হ্যান্ডলারটি ব্যবহার করতে পারেন। এখানে উদাহরণ কোড

new Handler(Looper.getMainLooper()).post(new Runnable() {
                                                        @Override
                                                        public void run() {
                                                           //do stuff like remove view etc
                                                            adapter.remove(selecteditem);
                                                        }
                                                    });

7

আমি দেখতে পাচ্ছি যে আপনি @ প্রভিডেন্সের উত্তর গ্রহণ করেছেন। কেবলমাত্র, আপনি হ্যান্ডলারটিও ব্যবহার করতে পারেন! প্রথমে ইনট ফিল্ডগুলি করুন।

    private static final int SHOW_LOG = 1;
    private static final int HIDE_LOG = 0;

এরপরে, ক্ষেত্র হিসাবে হ্যান্ডলার উদাহরণ তৈরি করুন।

    //TODO __________[ Handler ]__________
    @SuppressLint("HandlerLeak")
    protected Handler handler = new Handler()
    {
        @Override
        public void handleMessage(Message msg)
        {
            // Put code here...

            // Set a switch statement to toggle it on or off.
            switch(msg.what)
            {
            case SHOW_LOG:
            {
                ads.setVisibility(View.VISIBLE);
                break;
            }
            case HIDE_LOG:
            {
                ads.setVisibility(View.GONE);
                break;
            }
            }
        }
    };

একটি পদ্ধতি তৈরি করুন।

//TODO __________[ Callbacks ]__________
@Override
public void showHandler(boolean show)
{
    handler.sendEmptyMessage(show ? SHOW_LOG : HIDE_LOG);
}

অবশেষে, এটি onCreate()পদ্ধতিতে রাখুন।

showHandler(true);

7

আমার একই রকম সমস্যা ছিল এবং আমার সমাধানটি কুৎসিত, তবে এটি কার্যকর:

void showCode() {
    hideRegisterMessage(); // Hides view 
    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            showRegisterMessage(); // Shows view
        }
    }, 3000); // After 3 seconds
}

2
@ আর জাজাদেহ এটা শুনে ভাল লাগল। যেহেতু মুহূর্ত আমি যে উত্তর লিখেছিলেন, সম্ভবত এখন আপনি এটা ভালো কিছু করতে পারি :)
Błażej

6

আমি Handlerসঙ্গে ব্যবহার Looper.getMainLooper()। এটা আমার জন্য ভাল কাজ করেছিল.

    Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
              // Any UI task, example
              textView.setText("your text");
        }
    };
    handler.sendEmptyMessage(1);

5

এই কোডটি ব্যবহার করুন এবং runOnUiThreadকাজ করার দরকার নেই :

private Handler handler;
private Runnable handlerTask;

void StartTimer(){
    handler = new Handler();   
    handlerTask = new Runnable()
    {
        @Override 
        public void run() { 
            // do something  
            textView.setText("some text");
            handler.postDelayed(handlerTask, 1000);    
        }
    };
    handlerTask.run();
}

5

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

এখানে চিত্র বিবরণ লিখুন

উপরের ছবিতে, অগ্রগতি পরিবর্তনশীলটি ইউআই থ্রেডের জায়গার ভিতরে রয়েছে। সুতরাং, কেবলমাত্র ইউআই থ্রেড এই পরিবর্তনশীলটি অ্যাক্সেস করতে পারে। এখানে, আপনি নতুন থ্রেড () এর মাধ্যমে অগ্রগতি অ্যাক্সেস করছেন এবং এজন্য আপনি একটি ত্রুটি পেয়েছেন।


4

এটি আমার ক্ষেত্রে হয়েছিল যখন আমি ব্যবহারের পরিবর্তে কোনও doInBackgroundথেকে কোনও ইউআই পরিবর্তন Asynctaskকরার ডাক দিয়েছিলাম onPostExecute

onPostExecuteআমার সমস্যার সমাধান করতে ইউআইয়ের সাথে ডিল করা।


1
ধন্যবাদ জোনাথন এটি আমার সমস্যাও ছিল তবে এখানে আপনি কী বোঝাতে চেয়েছিলেন তা বোঝার জন্য আমাকে আরও কিছুটা পড়তে হয়েছিল। অন্য কারও onPostExecuteজন্যও এটি একটি পদ্ধতি AsyncTaskতবে এটি ইউআই থ্রেডে চলে। এখানে দেখুন: blog.teamtreehouse.com/all-about-android-asynctasks
ciaranodc

4

কোটলিন কর্টিনগুলি আপনার কোডটিকে আরও সংক্ষিপ্ত এবং এর মতো পাঠযোগ্য করে তুলতে পারে:

MainScope().launch {
    withContext(Dispatchers.Default) {
        //TODO("Background processing...")
    }
    TODO("Update UI here!")
}

বা তদ্বিপরীত:

GlobalScope.launch {
    //TODO("Background processing...")
    withContext(Dispatchers.Main) {
        // TODO("Update UI here!")
    }
    TODO("Continue background processing...")
}

3

আমি এমন একটি ক্লাসের সাথে কাজ করছিলাম যার প্রসঙ্গে কোনও উল্লেখ নেই। সুতরাং এটা সম্ভব আমাকে ব্যবহার করার জন্য ছিল না runOnUIThread();আমি ব্যবহৃত view.post();এবং এটি সমাধান করা হয়।

timer.scheduleAtFixedRate(new TimerTask() {

    @Override
    public void run() {
        final int currentPosition = mediaPlayer.getCurrentPosition();
        audioMessage.seekBar.setProgress(currentPosition / 1000);
        audioMessage.tvPlayDuration.post(new Runnable() {
            @Override
            public void run() {
                audioMessage.tvPlayDuration.setText(ChatDateTimeFormatter.getDuration(currentPosition));
            }
        });
    }
}, 0, 1000);

এর উপমা কি audioMessageএবং tvPlayDurationপ্রশ্ন কোড কিভাবে?
gotwo

audioMessageপাঠ্য প্রদর্শনের ধারক অবজেক্ট। tvPlayDurationএকটি পাঠ্যদর্শন যা আমরা কোনও ইউআই থ্রেড থেকে আপডেট করতে চাই। উপরের প্রশ্নে, currentTimeপাঠ্য দর্শনটি কিন্তু এতে কোনও ধারক অবজেক্ট নেই।
ইফতা

3

যখন ব্যবহার AsyncTask আপডেট মধ্যে UI 'তে onPostExecute পদ্ধতি

    @Override
    protected void onPostExecute(String s) {
   // Update UI here

     }

এটা আমার সাথে ঘটেছিল আমি অ্যাসিঙ্ক টাস্কের ডিনব্যাকগ্রাউন্ডে ইউআই আপডেট করছি।
মেহমুডনিসার 125

3

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

Device.BeginInvokeOnMainThread(() =>
    {
        myMethod();
    });

আমি এই রত্নটি এখানে পেয়েছি ।


2

এটি উল্লিখিত ব্যতিক্রমগুলির স্ট্যাক ট্রেস

        at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6149)
        at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:843)
        at android.view.View.requestLayout(View.java:16474)
        at android.view.View.requestLayout(View.java:16474)
        at android.view.View.requestLayout(View.java:16474)
        at android.view.View.requestLayout(View.java:16474)
        at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:352)
        at android.view.View.requestLayout(View.java:16474)
        at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:352)
        at android.view.View.setFlags(View.java:8938)
        at android.view.View.setVisibility(View.java:6066)

সুতরাং যদি আপনি গিয়ে খনন করেন তবে আপনি জানতে পারবেন

void checkThread() {
    if (mThread != Thread.currentThread()) {
        throw new CalledFromWrongThreadException(
                "Only the original thread that created a view hierarchy can touch its views.");
    }
}

যেখানে এমট্রেড নীচের মত কনস্ট্রাক্টর এ আরম্ভ করা হয়

mThread = Thread.currentThread();

আমি বলতে চাইছি আমরা যখন নির্দিষ্ট দৃষ্টিভঙ্গি তৈরি করি তখন আমরা এটি ইউআই থ্রেডে তৈরি করেছিলাম এবং পরে কোনও কর্মী থ্রেডে সংশোধন করার চেষ্টা করি।

নীচে কোড স্নিপেটের মাধ্যমে আমরা এটি যাচাই করতে পারি

Thread.currentThread().getName()

যখন আমরা লেআউট স্ফীত করি এবং পরে যেখানে আপনি ব্যতিক্রম পাচ্ছেন।


2

আপনি যদি runOnUiThreadএপিআই ব্যবহার করতে না চান , তবে বাস্তবে আপনি AsynTaskযে ক্রিয়াকলাপগুলি শেষ হতে কয়েক সেকেন্ড সময় নেয় তা প্রয়োগ করতে পারেন । তবে doinBackground()সেক্ষেত্রে আপনার কাজ প্রক্রিয়া করার পরেও আপনাকে সমাপ্ত ভিউটি ফিরে আসতে হবে onPostExecute()। অ্যান্ড্রয়েড বাস্তবায়ন কেবলমাত্র প্রধান UI থ্রেডকে দর্শনের সাথে ইন্টারঅ্যাক্ট করার অনুমতি দেয়।


2

যদি আপনি কেবল আপনার অ ইউআই থ্রেড থেকে (কল পুনরায় রঙ / পুনরায় আঁকা ফাংশন) অকার্যকর করতে চান, তবে পোস্টআইনফোর্ডেট () ব্যবহার করুন

myView.postInvalidate();

এটি ইউআই-থ্রেডে একটি অকার্যকর অনুরোধ পোস্ট করবে।

আরও তথ্যের জন্য: পোস্ট -বৈদ্যুতিন-কী করবেন


1

আমার জন্য সমস্যাটি ছিল আমি onProgressUpdate()আমার কোড থেকে স্পষ্টভাবে কল করছি। এটি করা উচিত নয়। আমি publishProgress()পরিবর্তে ফোন করেছি এবং এটি ত্রুটিটি সমাধান করেছে।


1

আমার ক্ষেত্রে, আমার EditTextঅ্যাডাপ্টারে রয়েছে এবং এটি ইতিমধ্যে ইউআই থ্রেডে রয়েছে। যাইহোক, যখন এই ক্রিয়াকলাপটি লোড হয়, তখন এই ত্রুটিটি দিয়ে ক্রাশ হয়।

আমার সমাধানটি হল <requestFocus />XML এডিটেক্সট থেকে আমার সরিয়ে নেওয়া দরকার ।


1

কোটলিনে লড়াই করা মানুষের জন্য, এটি এইভাবে কাজ করে:

lateinit var runnable: Runnable //global variable

 runOnUiThread { //Lambda
            runnable = Runnable {

                //do something here

                runDelayedHandler(5000)
            }
        }

        runnable.run()

 //you need to keep the handler outside the runnable body to work in kotlin
 fun runDelayedHandler(timeToWait: Long) {

        //Keep it running
        val handler = Handler()
        handler.postDelayed(runnable, timeToWait)
    }

0

সমাধান করা হয়েছে: এই পদ্ধতিটি কেবল ডাইনব্যাকগ্রাউন্ড ক্লাসে রেখে দিন ... এবং বার্তাটি পাস করুন

public void setProgressText(final String progressText){
        Handler handler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                // Any UI task, example
                progressDialog.setMessage(progressText);
            }
        };
        handler.sendEmptyMessage(1);

    }

0

আমার ক্ষেত্রে, কলকারী খুব অল্প সময়ের মধ্যে অনেকবার কল করলে এই ত্রুটিটি পাওয়া যাবে, আমি খুব অল্প সময়ের মধ্যে কিছু না করার জন্য কেবল অতিবাহিত সময় যাচাই করেছিলাম, উদাহরণস্বরূপ, যদি ফাংশনটি 0.5 সেকেন্ডের চেয়ে কম বলা হয় তবে উপেক্ষা করুন:

    private long mLastClickTime = 0;

    public boolean foo() {
        if ( (SystemClock.elapsedRealtime() - mLastClickTime) < 500) {
            return false;
        }
        mLastClickTime = SystemClock.elapsedRealtime();

        //... do ui update
    }

আরও ভাল সমাধান হ'ল ক্লিকের বোতামটি অক্ষম করা এবং ক্রিয়াটি সম্পূর্ণ হলে এটি আবার সক্ষম করে।
lsrom

@lsrom আমার ক্ষেত্রে এটি সহজ নয় কারণ কলারটি তৃতীয় পক্ষের লাইব্রেরি অভ্যন্তরীণ এবং আমার নিয়ন্ত্রণের বাইরে।
ফলের

0

যদি আপনি কোনও ইউআইটিথ্রেড না খুঁজে পান তবে আপনি এই উপায়টি ব্যবহার করতে পারেন।

yourcontcontext এর অর্থ, আপনার বর্তমান প্রসঙ্গে পার্স করা দরকার

 new Thread(new Runnable() {
        public void run() {
            while (true) {
                (Activity) yourcurrentcontext).runOnUiThread(new Runnable() {
                    public void run() { 
                        Log.d("Thread Log","I am from UI Thread");
                    }
                });
                try {
                    Thread.sleep(1000);
                } catch (Exception ex) {

                }
            }
        }
    }).start();

0

কোটলিন উত্তর

সত্যিকারের উপায়ে কাজের জন্য আমাদের ইউআই থ্রেড ব্যবহার করতে হবে। আমরা কোটলিনে ইউআই থ্রেড ব্যবহার করতে পারি:

runOnUiThread(Runnable {
   //TODO: Your job is here..!
})

@canerkaseler


0

ইন Kotlin কেবল runOnUiThread কার্যকলাপ পদ্ধতিতে আপনার কোড করা

runOnUiThread{
    // write your code here, for example
    val task = Runnable {
            Handler().postDelayed({
                var smzHtcList = mDb?.smzHtcReferralDao()?.getAll()
                tv_showSmzHtcList.text = smzHtcList.toString()
            }, 10)

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