Android “Only the original thread that created a view hierarchy can touch its views.”

后端 未结 28 3185
鱼传尺愫
鱼传尺愫 2020-11-21 04:44

I\'ve built a simple music player in Android. The view for each song contains a SeekBar, implemented like this:

public class Song extends Activity implement         


        
相关标签:
28条回答
  • 2020-11-21 05:10

    For the people struggling in Kotlin, it works like this:

    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 讨论(0)
  • 2020-11-21 05:11

    Solved : Just put this method in doInBackround Class... and pass the message

    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)
  • 2020-11-21 05:13

    I've been in this situation, but I found a solution with the Handler Object.

    In my case, I want to update a ProgressDialog with the observer pattern. My view implements observer and overrides the update method.

    So, my main thread create the view and another thread call the update method that update the ProgressDialop and....:

    Only the original thread that created a view hierarchy can touch its views.

    It's possible to solve the problem with the Handler Object.

    Below, different parts of my code:

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

    This explanation can be found on this page, and you must read the "Example ProgressDialog with a second thread".

    0 讨论(0)
  • 2020-11-21 05:13

    You can use Handler to Delete View without disturbing the main UI Thread. Here is example code

    new Handler(Looper.getMainLooper()).post(new Runnable() {
                                                            @Override
                                                            public void run() {
                                                               //do stuff like remove view etc
                                                                adapter.remove(selecteditem);
                                                            }
                                                        });
    
    0 讨论(0)
  • 2020-11-21 05:13

    I see that you have accepted @providence's answer. Just in case, you can also use the handler too! First, do the int fields.

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

    Next, make a handler instance as a field.

        //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;
                }
                }
            }
        };
    

    Make a method.

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

    Finally, put this at onCreate() method.

    showHandler(true);
    
    0 讨论(0)
  • 2020-11-21 05:14

    In Kotlin simply put your code in runOnUiThread activity method

    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)
    }
    
    0 讨论(0)
提交回复
热议问题