ඇන්ඩ්‍රොයිඩ් “දර්ශන ධූරාවලියක් නිර්මාණය කළ මුල් නූල් වලට පමණක් එහි අදහස් ස්පර්ශ කළ හැකිය.”


973

මම ඇන්ඩ්‍රොයිඩ් හි සරල සංගීත වාදකයක් ගොඩනගා ඇත්තෙමි. සෑම ගීතයකම දර්ශනයේ සීක්බාර් අඩංගු වන අතර එය මේ ආකාරයට ක්‍රියාත්මක වේ:

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()- සහ එය මට මෙම පැමිණිල්ල ලබා නොදේ.

Answers:


1945

UI යාවත්කාලීන කරන පසුබිම් කාර්යයේ කොටස ඔබ ප්‍රධාන ත්‍රෙඩ් එකට ගෙන යා යුතුය. මේ සඳහා සරල කේත කැබැල්ලක් තිබේ:

runOnUiThread(new Runnable() {

    @Override
    public void run() {

        // Stuff that updates the UI

    }
});

සඳහා ලියකියවිලි Activity.runOnUiThread.

පසුබිමේ ක්‍රියාත්මක වන ක්‍රමවේදය තුළ මෙය කැදැල්ල කර, පසුව බ්ලොක් මැද ඕනෑම යාවත්කාලීනයන් ක්‍රියාත්මක කරන කේතය පිටපත් කරන්න. හැකි කුඩාම කේත පමණක් ඇතුළත් කරන්න, එසේ නොමැතිනම් ඔබ පසුබිම් නූල්වල අරමුණ පරාජය කිරීමට පටන් ගනී.


5
චාම් එකක් වගේ වැඩ කළා. මට මෙහි ඇති එකම ගැටළුව වන්නේ මට error.setText(res.toString());ධාවන () ක්‍රමයක් කිරීමට අවශ්‍ය වීමයි , නමුත් මට එය භාවිතා කිරීමට නොහැකි වූයේ එය අවසාන නොවන නිසාය .. ඉතා නරකයි
noloman

65
මේ පිළිබඳව එක් කෙටි අදහසක්. මට වෙනම නූල් එකක් තිබී ඇති අතර එය UI වෙනස් කිරීමට උත්සාහ කළ අතර ඉහත කේතය ක්‍රියාත්මක විය, නමුත් මට ක්‍රියාකාරී වස්තුවෙන් runOnUiThread අමතන්න. මට එවැනි දෙයක් කිරීමට සිදු විය myActivityObject.runOnUiThread(etc)
කිරිබි

1
Ir කිර්බි මෙම සඳහනට ස්තූතියි. ඔබට හුදෙක් 'MainActivity.this' කළ හැකි අතර එයද ක්‍රියාත්මක විය යුතුය, එබැවින් ඔබේ ක්‍රියාකාරකම් පන්තිය ගැන සඳහන් නොකල යුතුය.
JRomero

25
එය runOnUiThread()ක්‍රියාකාරී ක්‍රමයක් බව වටහා ගැනීමට මට යම් කාලයක් ගත විය . මම මගේ කේතය කැබැල්ලකින් ධාවනය කරමින් සිටියෙමි. මම වැඩ අවසන් කර getActivity().runOnUiThread(etc)එය ක්‍රියාත්මක විය. නියමයි!;
lejonl

'RunOnUiThread' ක්‍රමවේදය තුළ ලියා ඇති කාර්යය අපට නතර කළ හැකිද?
කරන් ෂර්මා

145

මම දැමීම මගින් මෙම විසඳා 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);ඇතුළත නොවීමයි, එසේ නොමැතිනම් ඔබගේ UI පොරොත්තු කාලය තුළ කැටි වනු ඇත. AsyncTaskමෙවැනි මෙහෙයුම් සඳහා නූල් වෙනුවට භාවිතා කිරීම ගැන සලකා බැලිය යුතුය .
මාටින්

මතක කාන්දු වීම සඳහා මෙය එතරම්ම නරකයි
රෆායෙල් ලීමා

සමමුහුර්ත කොටසට කරදර වන්නේ ඇයි? එහි ඇති කේතය සාධාරණ ලෙස නූල් ආරක්ෂිත බව පෙනේ (මම මගේ වචන අනුභව කිරීමට සම්පූර්ණයෙන්ම සූදානම් වුවද).
ඩේවිඩ්

71

මේ සඳහා මගේ විසඳුම:

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()සිදුවීම සහ සිදුවීම් හැසිරවීම ක්‍රියාත්මක කරනු ලැබේ. එය සහතික කර ගත හැකි එක් ක්‍රමයක් වන්නේ runOnUiThread () භාවිතා කිරීමයි , තවත් ක්‍රමයක් වන්නේ හෑන්ඩ්ලර්ස් ය .

ProgressBar.setProgress() එය සෑම විටම ප්‍රධාන නූල් මත ක්‍රියාත්මක වන යාන්ත්‍රණයක් ඇත, එබැවින් එය ක්‍රියාත්මක වූයේ එබැවිනි.

වේදනා රහිත නූල් බලන්න .



20

මම මේ තත්වයේ සිටිමි, නමුත් මම හෑන්ඩ්ලර් වස්තුව සමඟ විසඳුමක් සොයා ගතිමි.

මගේ නඩුවේදී, නිරීක්ෂක රටාව සමඟ ProgressDialog යාවත්කාලීන කිරීමට මට අවශ්‍යය . මගේ දැක්ම නිරීක්ෂකයා ක්‍රියාත්මක කරන අතර යාවත්කාලීන ක්‍රමය ඉක්මවා යයි.

ඉතින්, මගේ ප්‍රධාන නූල මඟින් දර්ශනය නිර්මාණය කරන අතර තවත් ත්‍රෙඩ් එකක් ප්‍රගති ඩයලොප් යාවත්කාලීන කරන යාවත්කාලීන ක්‍රමය අමතන්න සහ ....:

දර්ශන ධූරාවලියක් නිර්මාණය කළ මුල් නූලට පමණක් එහි අදහස් ස්පර්ශ කළ හැකිය.

හෑන්ඩ්ලර් වස්තුව සමඟ ගැටළුව විසඳා ගත හැකිය.

පහත, මගේ කේතයේ විවිධ කොටස්:

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

ප්‍රධාන UI ත්‍රෙඩ් එකට බාධා නොකර දර්ශනය මකා දැමීමට ඔබට හැන්ඩ්ලර් භාවිතා කළ හැකිය. මෙන්න උදාහරණ කේතය

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

8

කොට්ලින් කොරොටින් වලට ඔබේ කේතය වඩාත් සංක්ෂිප්ත හා කියවිය හැකි පරිදි කළ හැකිය:

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...")
}

7

ඔබ ප්‍රොවිඩන්ස්ගේ පිළිතුර පිළිගෙන ඇති බව මට පෙනේ. ඔබට හසුරුවන්නා ද භාවිතා කළ හැකිය! පළමුව, int ක්ෂේත්‍ර කරන්න.

    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
@ R.jzadeh එය ඇසීම සතුටක්. මා එම පිළිතුර ලියා ඇති මොහොතේ සිට, දැන් ඔබට එය වඩා හොඳින් කළ හැකිය :)
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

මෙය පැහැදිලිවම දෝෂයකි. එය පවසන්නේ කුමන නූලෙන් දර්ශනයක් නිර්මාණය වී ඇත්ද යන්න එහි අදහස් ස්පර්ශ කළ හැකි බවයි. එයට හේතුව නිර්මාණය කරන ලද දර්ශනය එම නූල් අවකාශය තුළ ඇති බැවිනි. දර්ශන නිර්මාණය (GUI) සිදුවන්නේ UI (ප්‍රධාන) නූලෙනි. එමනිසා, ඔබ සැමවිටම UI නූල් භාවිතා කරන්නේ එම ක්‍රම වෙත ප්‍රවේශ වීම සඳහා ය.

රූප විස්තරය මෙහි ඇතුළත් කරන්න

ඉහත පින්තූරයේ, ප්‍රගති විචල්‍යය UI නූල් අවකාශය තුළ ඇත. එබැවින්, මෙම විචල්‍යයට ප්‍රවේශ විය හැක්කේ UI නූල් වලට පමණි. මෙන්න, ඔබ නව Thread () හරහා ප්‍රගතියට ප්‍රවේශ වන අතර ඔබට දෝෂයක් ඇති වූයේ එබැවිනි.


4

මෙය භාවිතා කිරීම වෙනුවට A doInBackgroundවෙතින් UI වෙනසක් ඉල්ලා සිටි විට මට මෙය සිදුවියAsynctaskonPostExecute .

UI සමඟ කටයුතු කිරීම onPostExecuteමගේ ගැටලුව විසඳීය.


1
ස්තූතියි ජොනතන්. මෙය මගේ ප්‍රශ්නය ද වූ නමුත් ඔබ මෙහි අදහස් කළේ කුමක්ද යන්න තේරුම් ගැනීමට මට තව ටිකක් කියවීමට සිදු විය. වෙනත් ඕනෑම කෙනෙකුට, onPostExecuteමෙයද ක්‍රමයක් වන AsyncTaskනමුත් එය UI නූල් මත ක්‍රියාත්මක වේ. මෙහි බලන්න: blog.teamtreehouse.com/all-about-android-asynctasks
ciaranodc

4

මම ඒ හා සමාන ගැටලුවකට මුහුණ දුන් අතර ඉහත සඳහන් කළ ක්‍රම කිසිවක් මට ප්‍රයෝජනවත් නොවීය. අවසානයේදී, මෙය මට උපක්‍රමයක් විය:

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

මට මේ මැණික හමු විය .


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යනු පෙළ දර්ශනයේ දරන්නාගේ වස්තුවකි. tvPlayDurationUI නොවන ත්‍රෙඩ් එකකින් අපට යාවත්කාලීන කිරීමට අවශ්‍ය පෙළ දසුනයි. ඉහත ප්‍රශ්නයේ දී, currentTimeපෙළ දර්ශනය වන නමුත් එයට දරන්නාගේ වස්තුවක් නොමැත.
ඉෆ්ටා

3

AsyncTask භාවිතා කරන විට onPostExecute ක්‍රමයේදී UI යාවත්කාලීන කරන්න

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

     }

මෙය මට සිදු විය. මම අසයික් කාර්යයේ පසුබිම තුළ යූඅයි යාවත්කාලීන කරමින් සිටියෙමි.
mehmoodnisar125

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 පහත වගේ ඉදිකිරීමටත් දී ආරම්භනය වේ

mThread = Thread.currentThread();

මා අදහස් කිරීමට අදහස් කළේ අප විශේෂිත දර්ශනයක් නිර්මාණය කළ විට එය UI Thread මත නිර්මාණය කර පසුව සේවක ත්‍රෙඩ් එකක වෙනස් කිරීමට උත්සාහ කරන බවයි.

පහත කේත ස්නිපටය හරහා අපට එය සත්‍යාපනය කළ හැකිය

Thread.currentThread().getName()

අපි පිරිසැලසුම උඩුගත කරන විට සහ පසුව ඔබට ව්‍යතිරේකයක් ලැබෙන විට.


2

ඔබට runOnUiThreadAPI භාවිතා කිරීමට අවශ්‍ය නැතිනම් , ඇත්ත වශයෙන්ම ඔබට AsynTaskසම්පූර්ණ කිරීමට තත්පර කිහිපයක් ගතවන මෙහෙයුම් සඳහා ක්‍රියාත්මක කළ හැකිය . නමුත් එවැනි අවස්ථාවකදී, ඔබේ වැඩ කටයුතු සැකසීමෙන් පසුවද doinBackground(), ඔබ විසින් නිමි දර්ශනය නැවත ලබා දිය යුතුය onPostExecute(). ඇන්ඩ්‍රොයිඩ් ක්‍රියාත්මක කිරීම මඟින් ප්‍රධාන UI නූල් වලට පමණක් අදහස් සමඟ අන්තර් ක්‍රියා කිරීමට ඉඩ ලබා දේ.


2

ඔබේ UI නොවන ත්‍රෙඩ් එකෙන් අවලංගු කිරීමට (නැවත කැඳවීම / නැවත ඇඳීම) අමතන්න, postInvalidate () භාවිතා කරන්න.

myView.postInvalidate();

මෙය UI-thread හි අවලංගු ඉල්ලීමක් පළ කරනු ඇත.

වැඩි විස්තර සඳහා: what-do-postinvalidate-do


1

මට නම් ගැටලුව වූයේ මම onProgressUpdate()පැහැදිලිවම මගේ කේතයෙන් ඇමතීමයි. මෙය සිදු නොකළ යුතුය. මම publishProgress()ඒ වෙනුවට කතා කළ අතර එය දෝෂය විසඳීය.


1

මගේ නඩුවේ, මට EditTextඇඩැප්ටරයේ ඇත, එය දැනටමත් UI ත්‍රෙඩ් එකේ ඇත. කෙසේ වෙතත්, මෙම ක්‍රියාකාරකම පූරණය වන විට, එය මෙම දෝෂය සමඟ බිඳ වැටේ.

මගේ විසඳුම වන්නේ <requestFocus />XML හි EditText වෙතින් ඉවත් කිරීමයි.


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

1

කෝට්ලින් පිළිතුර

අපි රැකියාව සඳහා UI Thread භාවිතා කළ යුතුයි. අපට කෝට්ලින්හි UI Thread භාවිතා කළ හැකිය:

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

@canerkaseler


0

විසඳා ඇත: මෙම ක්‍රමය doInBackround පන්තියට ඇතුළත් කර පණිවිඩය යවන්න

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

ඔබට UIThread එකක් සොයාගත නොහැකි නම් ඔබට මේ ආකාරයෙන් භාවිතා කළ හැකිය.

yourcurrentcontext යන්නෙන් අදහස් කරන්නේ, ඔබ වත්මන් සන්දර්භය විග්‍රහ කළ යුතුය

 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

දී 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)
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.