如何使用从另一个线程收到的信息更新主UI? (虽然线程仍在运行)

时间:2011-08-19 23:56:27

标签: java android user-interface

我正试图在运行时尝试更新屏幕元素。但我不能让这个工作。

以下是一些示例代码

public static TextView CurrentConnectionAttempt;
        CurrentConnectionAttempt = (TextView) findViewById(R.id.CurrentConnectionAttempt);

        IntentFilter afilter= new IntentFilter("SomeSortOfFilter"); 
        registerReceiver(SomeReceiver, afilter);

    private BroadcastReceiver SomeReceiver= new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {    
        for (int i = 0; i<100; 1++ ) 
        {           
            String connectionAttempt = "This is loop Iteration " + i;
            CurrentConnectionAttempt.setText(connectionAttempt);                    
            doSomething("Some Parameter");          
        }
       }
};

我想要发生的是用“i”的每个新值更新屏幕Textview,然后执行一个函数。我想这个例子类似于进度条。

部分是在广播事件中发现的信息。因此,在主UI线程中找不到该信息。这就是Async任务和其他多线程选项对我不起作用的原因。 (根据我的理解)

我研究了这些解决方案。

  1. 创建可运行的
  2. 我尝试过AyncTask
  3. 创建第二个广播接收器
  4. 也许我忽视了一些明显的东西,或者也许不可能以这种方式影响主UI线程。任何建议和/或示例表示赞赏。

    谢谢!

    编辑:我的异步任务非常基本,我尝试过。我甚至尝试过各种变化。我认为我的问题可能类似于我刚才在这个博客上看到的内容。 Async problems

    这里发生的是广播接收器将遍历所有循环迭代,并且异步任务中的doInBackground函数将同时触发,但是直到广播接收器完全执行完毕才会触发onProgressUpdate函数。然后onProgressUpdate和onPostExecute将多次执行。我的猜测是,由于广播接收器位于与UI不同的线程上,因此需要在另一个子线程能够工作之前完全执行。

    这是我的代码,

    在我的广播接收器中:

        UpdateDynamicDisplay2 testDisplay= new UpdateDynamicDisplay2();
                        testDisplay.execute(connectionAttempt );
    
        // This is a sub class in my main class
    class UpdateDynamicDisplay2 extends AsyncTask<String, String, String>{
    
        String Testing1;
    
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
    
            }
    
            @Override
            protected String doInBackground(String... aurl) {
                publishProgress(aurl[0]);
                Testing1 = aurl[0];
                    MyMainClass.CurrentConnectionAttempt.setText(Testing1);
                return Testing1;
            }
    
            protected void onProgressUpdate(String... progress) {
                MyMainClass.CurrentConnectionAttempt.setText(progress[0]);
            }
    
            @Override
            protected void onPostExecute(String unused) {   
                MyMainClass.CurrentConnectionAttempt.setText(unused);
            }
        }
    

    希望这已经足够了。

3 个答案:

答案 0 :(得分:2)

问题是您正在尝试通过静态变量直接从BroadcastReceiver更新UI。 AsyncTask意味着由Activity使用,而不是BroadcastReceiver。

更好的方法是让您的BroadcastReceiver更新数据源,并让您的Activity监视该数据源。

如果您要处理大量数据,那么最好的办法是创建ContentProvider然后register a ContentObserver以便在数据发生变化时收到通知。

如果您只需要为单个值执行此操作,那么SharedPreferences可能是一种更简单的方法。在这种情况下,您还可以注册监听器以进行更改。

最后,您可以创建一个单例并使用数据结构将数据保存在内存中。您可以实现自己的Observer pattern版本,以便在数据发生变化时收到通知。这可能不是一个好的长期解决方案,因为Android环境不会对您的内存对象做出任何长期保证。

答案 1 :(得分:1)

这个问题和它的答案将让你通过你应该到达的确切位置!处理程序有效但不值得推荐。在Android中AsycTask更好更易读。

How to let Asynctask update UI in different ways

快乐的编码!

<强> EDITED

此链接包含一些源代码,如何更新进度条,例如1到100,

http://ketankantilal.blogspot.com/2011/05/how-to-update-progress-bar-using-thread.html

祝你好运

答案 2 :(得分:0)

最简单的方法可能是通过处理程序

private Handler handler; //Global Decalration
...
handler = new Handler(); //This is declared in the Main UI thread (onCreate)

然后在正在进行工作的线程中:

handler.post(new Runnable() {
@Override
public void run() {
   CurrentConnectionAttempt.setText(ConnectionAttempt);
}
});

希望这有效。