我们如何在Android中使用runOnUiThread?

时间:2012-06-21 14:21:50

标签: android ui-thread

我是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();
                    }
                }
             }
        }));
    }
}

12 个答案:

答案 0 :(得分:191)

以下是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();
}

答案 1 :(得分:77)

将其包装为函数,然后从后台线程中调用此函数。

public void debugMsg(String msg) {
    final String str = msg;
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mInfo.setText(str);
        }
    });
}

答案 2 :(得分:26)

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

相反,只需直接从点击处理程序启动后台线程。然后,将呼叫包含在btn.setText()的呼叫中runOnUiThread()

答案 3 :(得分:10)

runOnUiThread(new Runnable() {
                public void run() {
                //Do something on UiThread
            }
        });

答案 4 :(得分:8)

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

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

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

答案 5 :(得分:2)

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

getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
            //Do something on UiThread
        }
    });

答案 6 :(得分: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");


            }
        });
    }

答案 7 :(得分:1)

我们使用Worker Thread使应用程序更流畅并避免ANR。在工作程序Tread中进行了繁重的工作后,我们可能需要更新UI。 用户界面只能通过用户界面线程进行更新。在这种情况下,我们使用Handler或runOnUiThread都具有在UI Thread中执行的Runnable运行方法。 onClick方法在UI线程中运行,因此无需在此处使用runOnUiThread。

使用Kotlin

在活动中

this.runOnUiThread {
      // Do stuff
}

来自片段

activity?.runOnUiThread {
      // Do stuff
}

使用Java

this.runOnUiThread(new Runnable() {
     void run() {
         // Do stuff
     }
});

答案 8 :(得分:0)

您可以使用此示例:

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

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

当用户点击“搜索”按钮时,我们将创建一个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";
    }
}

来源

asynchronous android programming Helder Vasconcelos

答案 9 :(得分:0)

这就是我使用它的方式:

runOnUiThread(new Runnable() {
                @Override
                public void run() {
                //Do something on UiThread
            }
        });

答案 10 :(得分: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();

    }

答案 11 :(得分:0)

尝试以下操作:getActivity().runOnUiThread(new Runnable...

这是因为:

1)您对 runOnUiThread 的调用中的隐式引用是指 AsyncTask ,而不是您的片段。

2)片段没有runOnUiThread。

但是,活动确实如此。

请注意,如果您已经在主线程上,那么Activity仅执行Runnable,否则将使用Handler。如果您不想担心它的上下文,则可以在片段中实现Handler,这实际上非常简单:

//一个类实例

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

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

mHandler.post(<your runnable>);

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