174

我是 Android 新手,我正在尝试使用 UI-Thread,所以我编写了一个简单的测试活动。但我想我误解了一些东西,因为点击按钮 - 应用程序不再响应

public class TestActivity extends Activity {

    Button btn;
    int i = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btn = (Button)findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                runThread();
            }
        });
    }

    private void runThread(){
        runOnUiThread (new Thread(new Runnable() {  
            public void run() {
                while(i++ < 1000){
                    btn.setText("#"+i);
                    try {
                        Thread.sleep(300);
                    } 
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
             }
        }));
    }
}
4

13 回答 13

226

以下是更正的runThread功能片段。

private void runThread() {

    new Thread() {
        public void run() {
            while (i++ < 1000) {
                try {
                    runOnUiThread(new Runnable() {

                        @Override
                        public void run() {
                            btn.setText("#" + i);
                        }
                    });
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }.start();
}
于 2012-06-21T14:29:38.497 回答
98

只需将其包装为一个函数,然后从后台线程调用此函数。

public void debugMsg(String msg) {
    final String str = msg;
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mInfo.setText(str);
        }
    });
}
于 2015-01-16T20:56:04.170 回答
28

你有它从后到前。您的按钮单击会导致调用runOnUiThread(),但这不是必需的,因为单击处理程序已经在 UI 线程上运行。然后,您的代码runOnUiThread()正在启动一个新的后台线程,您尝试在其中执行 UI 操作,然后失败。

相反,只需直接从您的点击处理程序启动后台线程。然后,将调用包装到对btn.setText()的调用中runOnUiThread()

于 2012-06-21T14:24:31.143 回答
16
runOnUiThread(new Runnable() {
                public void run() {
                //Do something on UiThread
            }
        });
于 2015-11-04T20:15:55.697 回答
13

有几种使用 of 的技术runOnUiThread(),让我们看看所有

这是我的名为AndroidBasicThreadActivity的主线程(UI 线程),我将以各种方式从工作线程更新它 -

public class AndroidBasicThreadActivity extends AppCompatActivity
{
    public static TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_android_basic_thread);

        textView = (TextView) findViewById(R.id.textview);

        MyAndroidThread myTask = new MyAndroidThread(AndroidBasicThreadActivity.this);
        Thread t1 = new Thread(myTask, "Bajrang");
        t1.start();
    }
}

1.) 通过将 Activity 的实例作为参数传递给工作线程

class MyAndroidThread implements Runnable
{
    Activity activity;
    public MyAndroidThread(Activity activity)
    {
        this.activity = activity;
    }
    @Override
    public void run()
    {

        //perform heavy task here and finally update the UI with result this way - 
        activity.runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
                AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
            }
        });
    }
}

2.) 在工作线程中使用 View 的 post(Runnable runnable) 方法

class MyAndroidThread implements Runnable
{
    Activity activity;
    public MyAndroidThread(Activity activity)
    {
        this.activity = activity;
    }
    @Override
    public void run()
    {
     //perform heavy task here and finally update the UI with result this way - 
       AndroidBasicThreadActivity.textView.post(new Runnable()
      { 
        @Override
        public void run()
        {
            AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
        }
    });

    }
}

3.) 通过使用 android.os 包中 的 Handler 类 如果我们没有上下文 ( this/ getApplicationContext()) 或 Activity 的实例 ( AndroidBasicThreadActivity.this),那么我们必须使用 Handler 类,如下所示 -

class MyAndroidThread implements Runnable
{
    Activity activity;
    public MyAndroidThread(Activity activity)
    {
        this.activity = activity;
    }
    @Override
   public void run()
  {
  //perform heavy task here and finally update the UI with result this way - 
  new Handler(Looper.getMainLooper()).post(new Runnable() {
        public void run() {
            AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
        }
    });
  }
}
于 2017-02-16T12:51:20.737 回答
11

如果在片段中使用,则只需编写

getActivity().runOnUiThread(new Runnable() {
    @Override
    public void run() {
        // Do something on UiThread
    }
});
于 2019-03-15T10:32:48.193 回答
3

我们使用 Worker Thread 使应用程序更流畅并避免 ANR。在 worker Tread 的繁重过程之后,我们可能需要更新 UI。UI 只能从 UI Thread 更新。在这种情况下,我们使用 Handler 或 runOnUiThread 都有一个在 UI Thread 中执行的 Runnable run 方法。onClick 方法在 UI 线程中运行,因此这里不需要使用 runOnUiThread。

使用 Kotlin

在活动中,

this.runOnUiThread {
      // Do stuff
}

从片段,

activity?.runOnUiThread {
      // Do stuff
}

使用 Java ,

this.runOnUiThread(new Runnable() {
     void run() {
         // Do stuff
     }
});
于 2020-02-21T06:09:28.203 回答
1

你这个:

@UiThread
    public void logMsg(final String msg) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                Log.d("UI thread", "I am the UI thread");


            }
        });
    }
于 2017-03-10T02:42:03.460 回答
1

用于fragment

requireActivity().runOnUiThread(() -> {
//your code logic
});

用于activity

runOnUiThread(() -> {
//your code logic
});

runOnUiThread以一种可以使用我们的后台线程更新 UI 的方式使用。更多信息:https ://www.tutorialspoint.com/how-do-we-use-runonuithread-in-android

于 2022-01-28T15:22:46.650 回答
0

您可以从此示例中使用:

在以下示例中,我们将使用此工具发布由后台线程处理的同义词搜索的结果。

为了在 OnCreate 活动回调期间完成目标,我们将设置 onClickListener 以在创建的线程上运行 searchTask。

当用户单击 Search 按钮时,我们将创建一个 Runnable 匿名类,用于搜索 R.id.wordEt EditText 中键入的单词并启动线程以执行 Runnable。

搜索完成后,我们将创建一个 Runnable SetSynonymResult 实例,以通过 UI 线程将结果发布回同义词 TextView 上。

这种技术有时不是最方便的,尤其是当我们无法访问 Activity 实例时;因此,在接下来的章节中,我们将讨论从后台计算任务更新 UI 的更简单、更简洁的技术。

public class MainActivity extends AppCompatActivity {

    class SetSynonymResult implements Runnable {
        String synonym;

        SetSynonymResult(String synonym) {
            this.synonym = synonym;
        }

        public void run() {
            Log.d("AsyncAndroid", String.format("Sending synonym result %s on %d",
                    synonym, Thread.currentThread().getId()) + " !");
            TextView tv = (TextView) findViewById(R.id.synonymTv);
            tv.setText(this.synonym);
        }
    }

    ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button search = (Button) findViewById(R.id.searchBut);
        final EditText word = (EditText) findViewById(R.id.wordEt);
        search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Runnable searchTask = new Runnable() {
                    @Override
                    public void run() {
                        String result = searchSynomim(word.getText().toString());
                        Log.d("AsyncAndroid", String.format("Searching for synonym for %s on %s",
                                word.getText(), Thread.currentThread().getName()));
                        runOnUiThread(new SetSynonymResult(result));
                    }
                };
                Thread thread = new Thread(searchTask);
                thread.start();
            }
        });

    }

    static int i = 0;

    String searchSynomim(String word) {
        return ++i % 2 == 0 ? "fake" : "mock";
    }
}

来源

异步 android 编程 Helder Vasconcelos

于 2016-10-27T06:46:24.423 回答
0

这就是我使用它的方式:

runOnUiThread(new Runnable() {
                @Override
                public void run() {
                //Do something on UiThread
            }
        });
于 2016-12-26T01:22:09.557 回答
0
  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        gifImageView = (GifImageView) findViewById(R.id.GifImageView);
        gifImageView.setGifImageResource(R.drawable.success1);

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //dummy delay for 2 second
                    Thread.sleep(8000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //update ui on UI thread
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        gifImageView.setGifImageResource(R.drawable.success);
                    }
                });

            }
        }).start();

    }
于 2017-09-02T08:03:20.167 回答
0

试试这个:getActivity().runOnUiThread(new Runnable...

这是因为:

1)您调用runOnUiThread中隐含的 this 指的是AsyncTask,而不是您的片段。

2)片段没有runOnUiThread。

但是,活动确实如此。

请注意,如果您已经在主线程上,Activity 只会执行 Runnable,否则它使用 Handler。如果你不想担心上下文,你可以在你的片段中实现一个处理程序,这实际上很容易:

// 一个类实例

private Handler mHandler = new Handler(Looper.getMainLooper());

// 代码中的其他任何地方

mHandler.post(<your runnable>);

// ^ 这将始终在主线程的下一个运行循环中运行。

于 2019-11-26T11:25:32.137 回答