Java 如何从片段中的后台线程更新UI
我有一个应用程序,它有一个带有ListView的片段。我在网络上ping IP地址,当我得到响应时,我将IP地址添加到列表中。一旦我完成了对IP地址的ping操作,我会将响应ping操作的IP地址列表放入列表视图中 我要做的是在ping时更新此ListView,而不是在ping完所有IP地址后更新。为了ping IP地址,我使用了一个AsyncTask,然后调用一个可运行线程。当我找到一个IP地址时,如何告诉片段从该可运行类更新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
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使用Handler,runOnUiThread或View.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次,并使用AsyncTasksonProgressUpdate()
,它允许您从doInBackground()部分更新UI(在主UI线程上运行),其中,onPostExecute()
在我现在这样做之后只调用一次。我使用onPostExecute()但这会在doInBackground完成后更新ListView。我想在doInBackground运行时更新ListView.wtf?显然你在doInBackground()
中做了你的工作,然后在onPostExecute()
中更新列表。我不确定“一旦doInBackground()更新ListView”是什么意思…您可以运行20个AsyncTask,每个AsyncTask都在doInBackground()
中加载数据,然后在onPostExecute()
中更新列表视图,或者您可以编写一个AsyncTask,运行20次findDevices并使用AsyncTasksonProgressUpdate(