简体   繁体   English

如何从片段中的后台线程更新UI

[英]How to update UI from background thread in a fragment

I have an app that has a Fragment with a ListView. 我有一个带有Fragment和ListView的应用程序。 I ping IP addresses on the network and when I get a response I add the IP address to a list. 我在网络上ping IP地址,当收到响应时,将IP地址添加到列表中。 Once I've finished pinging the IP addresses, I put this list of IP addresses that replied to my ping into a ListView. 对IP地址执行ping操作之后,我将把已回复ping的IP地址列表放入ListView。

What I want to do is update this ListView as I'm pinging rather than doing after I've pinged all the IP addresses. 我要执行的操作是在ping时更新此ListView,而不是在ping所有IP地址之后执行此操作。 To ping the IP addresses I'm using an AsyncTask which then calls a Runnable Thread. 为了ping IP地址,我使用了AsyncTask,然后调用了Runnable Thread。 How do I tell the Fragment to update the UI from that Runnable class when I find an IP address? 找到IP地址后,如何告诉Fragment从该Runnable类更新UI?

The rough layout of my classes is below. 我的课程的大致布局如下。

public class FinderFragment extends ListFragment {

    private void CallFind(){
        new Find().execute();
    }

    private class Find extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... voids) {
            SearchNetwork searchNetwork = new SearchNetwork(ipAddress);
            try {
                searchNetwork.StartFind();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            UpdateDeviceList();
        }
    }
}

public class SearchNetwork {

    public void StartFind() throws InterruptedException {
        Thread t[] = new Thread[20];
        for(int i=0; i<02; i++){
            t[i] = new Thread(new FindDevices(i*5));
            t[i].start();
        }
        for(Thread thread : t){
            thread.join();
        }
    }

    class FindDevices implements Runnable{

        @Override
        public void run() {
            //Ping the IP addresses here
            //I want to update UI from here
        }
    }

Try this.... 尝试这个....

getActivity().runOnUiThread(new Runnable(){
            @Override
            public void run(){
               // Do whatever you want
               }
             });

You should use AsyncTask instead of raw threads! 您应该使用AsyncTask而不是原始线程! There is a method onPostExecute() which runs on the main UI thread and that's the point where you can update your UI ... 有一个方法onPostExecute()在主UI线程上运行,这就是您可以更新UI的地方。

But you have to keep in mind, that you have to cancel the AsyncTask (threads as well) if the fragment gets destroyed, otherwise your task will continue to run and will try to change the UI of the fragment, but the fragment doesn't exist anymore which will lead to exceptions like IllegalStateException: Fragment not attached to Activity or View Not Attached Exceptions 但是,请记住,如果片段被破坏,则必须取消AsyncTask(也包括线程),否则您的任务将继续运行并尝试更改片段的UI,但是片段不会不再存在,将导致诸如IllegalStateException: Fragment not attached to Activity异常IllegalStateException: Fragment not attached to ActivityView Not Attached Exceptions

We can use Handler , runOnUiThread , postDelayed and AsyncTask . 我们可以使用HandlerrunOnUiThreadpostDelayedAsyncTask
AsyncTask is good option other than rest as it extends the handler class. 除了扩展处理程序类外, AsyncTask是一个不错的选择,而不是休息。
When you have to code in thread use the doInBackground() method like this: 当您必须在线程中编码时,请使用doInBackground()方法,如下所示:

class myAsyncTask extends AsyncTask(Void,Void,Void){
    public doInBackground(){
        // do your code here
    }
}

And call it on the UI thread like this: 并在UI线程上这样调用它:

new MyAsyncTask().execute();

use Handler , runOnUiThread or View.post 使用HandlerrunOnUiThreadView.post

android.os.Handler handler = new android.os.Handler();
        handler.post(new Runnable() {
            @Override
            public void run() {
                //update here
            }
        });

if you want to auto update every x sec you can use this: 如果您想每隔x​​秒自动更新一次,可以使用以下命令:

Runnable runnable = new Runnable() {
        @Override
        public void run() {
            while(refreshing){
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        //do your stuff here
                    }
                });
                try{
                    Thread.sleep(30000);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
        }
    };
    new Thread(runnable).start();

Try 尝试

publishProgress()

and catch it in the overidden method 并以隐藏的方法捕获它

@Override
protected void onProgressUpdate(Void... values) {
    super.onProgressUpdate(values);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM