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

Java 如何从片段中的后台线程更新UI,java,android,multithreading,android-fragments,fragment,Java,Android,Multithreading,Android Fragments,Fragment,我有一个应用程序,它有一个带有ListView的片段。我在网络上ping IP地址,当我得到响应时,我将IP地址添加到列表中。一旦我完成了对IP地址的ping操作,我会将响应ping操作的IP地址列表放入列表视图中 我要做的是在ping时更新此ListView,而不是在ping完所有IP地址后更新。为了ping IP地址,我使用了一个AsyncTask,然后调用一个可运行线程。当我找到一个IP地址时,如何告诉片段从该可运行类更新UI 下面是我班级的大致布局 public class Finder

我有一个应用程序,它有一个带有ListView的片段。我在网络上ping IP地址,当我得到响应时,我将IP地址添加到列表中。一旦我完成了对IP地址的ping操作,我会将响应ping操作的IP地址列表放入列表视图中

我要做的是在ping时更新此ListView,而不是在ping完所有IP地址后更新。为了ping IP地址,我使用了一个AsyncTask,然后调用一个可运行线程。当我找到一个IP地址时,如何告诉片段从该可运行类更新UI

下面是我班级的大致布局

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
        }
    }
公共类FinderFragment扩展了ListFragment{
私有void CallFind(){
新建Find().execute();
}
私有类查找扩展异步任务{
@凌驾
受保护的空位背景(空位…空位){
SearchNetwork SearchNetwork=新的SearchNetwork(ipAddress);
试一试{
searchNetwork.StartFind();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
@凌驾
受保护的void onPostExecute(void避免){
super.onPostExecute(避免);
UpdateDeviceList();
}
}
}
公共类搜索网络{
public void StartFind()引发InterruptedException{
螺纹t[]=新螺纹[20];

对于(int i=0;i使用HandlerrunOnUiThreadView.post

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

使用处理程序runOnUiThread视图。发布

android.os.Handler handler = new android.os.Handler();
        handler.post(new Runnable() {
            @Override
            public void run() {
                //update here
            }
        });
您应该使用而不是原始线程!有一个方法
onPostExecute()
在主UI线程上运行,这就是您可以更新UI的点

但是您必须记住,您必须取消异步任务(以及线程)如果片段被销毁,否则您的任务将继续运行并尝试更改片段的UI,但该片段不再存在,这将导致异常,如
IllegalStateException:fragment not attached to Activity
View not attached exceptions

,您应该使用而不是原始的读取!有一个方法
onPostExecute()
在主UI线程上运行,这就是您可以更新UI的点

但是您必须记住,您必须取消异步任务(以及线程)如果片段被销毁,否则您的任务将继续运行并尝试更改片段的UI,但该片段不再存在,这将导致异常,如
IllegalStateException:fragment not attached to Activity
View not attached exceptions
尝试以下操作

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

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

我们可以使用
Handler
runOnUiThread
postDelayed
AsyncTask

AsyncTask
是rest以外的好选项,因为它扩展了处理程序类。
当您必须在线程中编码时,请使用
doInBackground()
方法,如下所示:

class myAsyncTask extends AsyncTask(Void,Void,Void){
    public doInBackground(){
        // do your code here
    }
}
new MyAsyncTask().execute();
并在UI线程上调用它,如下所示:

class myAsyncTask extends AsyncTask(Void,Void,Void){
    public doInBackground(){
        // do your code here
    }
}
new MyAsyncTask().execute();

我们可以使用
Handler
runOnUiThread
postDelayed
AsyncTask

AsyncTask
是rest以外的好选项,因为它扩展了处理程序类。
当您必须在线程中编码时,请使用
doInBackground()
方法,如下所示:

class myAsyncTask extends AsyncTask(Void,Void,Void){
    public doInBackground(){
        // do your code here
    }
}
new MyAsyncTask().execute();
并在UI线程上调用它,如下所示:

class myAsyncTask extends AsyncTask(Void,Void,Void){
    public doInBackground(){
        // do your code here
    }
}
new MyAsyncTask().execute();

如果要每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();

如果要每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();
试一试

publishProgress()

然后用超快的方法抓住它

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

publishProgress()

然后用超快的方法抓住它

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

您是否尝试过
getActivity().runOnUiThread
?请使用handler而不是它。请参考google sample的threadSample示例。您尝试过
getActivity()吗.runOnUiThread
?请使用处理程序,而不是它。请参考google sample的threadSample示例。抱歉,我才真正开始学习线程和异步任务,但仍然没有完全理解它们。该处理程序会进入我的FinderFragment类吗?抱歉,我才真正开始学习线程和异步任务d仍然不完全理解它们。该处理程序会进入我的FinderFragment类吗?我现在正在这样做。我使用onPostExecute(),但它会在doInBackground完成后更新ListView。我想在doInBackground运行时更新ListView.wtf?显然,在
doInBackground()中是这样做的
您在
onPostExecute()
中完成工作并随后更新列表。我不确定“一次更新ListView doInBackground()”是什么意思……您可以运行20个异步任务,每个任务都在
doInBackground()
中加载数据,然后在
onPostExecute()中更新ListView
或者您可以编写一个AsyncTask,它将运行findDevices 20次,并使用AsyncTasks
onProgressUpdate()
,它允许您从doInBackground()部分更新UI(在主UI线程上运行),其中,
onPostExecute()
在我现在这样做之后只调用一次。我使用onPostExecute()但这会在doInBackground完成后更新ListView。我想在doInBackground运行时更新ListView.wtf?显然你在
doInBackground()
中做了你的工作,然后在
onPostExecute()
中更新列表。我不确定“一旦doInBackground()更新ListView”是什么意思…您可以运行20个AsyncTask,每个AsyncTask都在
doInBackground()
中加载数据,然后在
onPostExecute()
中更新列表视图,或者您可以编写一个AsyncTask,运行20次findDevices并使用AsyncTasks
onProgressUpdate(