在android中从线程更新ui

sqyvllje  于 2021-07-06  发布在  Java
关注(0)|答案(7)|浏览(263)

我想从更新progressbar的线程更新ui。不幸的是,当从“runnable”更新progressbar的drawable时,progressbar消失了!更改progressbars的Drawing in onCreate() 在另一边工作!
有什么建议吗?

public void onCreate(Bundle savedInstanceState) {
    res = getResources();
    super.onCreate(savedInstanceState);
    setContentView(R.layout.gameone);
    pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); //**Works**/
    handler.postDelayed(runnable, 1);       
}

private Runnable runnable = new Runnable() {
    public void run() {  
        runOnUiThread(new Runnable() { 
            public void run() 
            { 
                //* The Complete ProgressBar does not appear**/                         
                pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); 
            } 
        }); 
    }
}
j5fpnvbx

j5fpnvbx1#

我见过的向ui线程提供短时间执行的最简单的解决方案是通过视图的post()方法。这是必需的,因为ui方法不是可重入的。其方法是:

package android.view;

public class View;

public boolean post(Runnable action);

post()方法对应于swingutilities.invokelater()。不幸的是,我没有找到与swingutilities.invokeandwait()相对应的简单方法,但是可以使用监视器和标志在前者的基础上构建后者。
所以你保存的是创建一个处理程序。你只需要找到你的观点,然后张贴在它。如果您倾向于使用id资源,可以通过findviewbyid()找到视图。生成的代码非常简单:

/* inside your non-UI thread */

view.post(new Runnable() {
        public void run() {
            /* the desired UI update */
        }
    });
}

注意:与swingutilities.invokelater()相比,view.post()方法确实返回一个布尔值,指示视图是否有关联的事件队列。因为我使用了invokelater()resp。反正post()只用于fire and forget,我没有检查结果值。基本上,只有在对视图调用onattachedtowindow()之后,才应该调用post()。
致以最诚挚的问候

eanckbw9

eanckbw92#

如果你使用 Handler (我看到您这样做了,希望您在ui线程上创建了它的示例),然后不要使用 runOnUiThread() 你的内心 runnable . runOnUiThread() 但是,在从非ui线程执行smth时使用 Handler 已经执行你的命令了 runnable 在ui线程上。
试着这样做:

private Handler mHandler = new Handler();
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.gameone);
    res = getResources();
    // pB.setProgressDrawable(getResources().getDrawable(R.drawable.green));**//Works**
    mHandler.postDelayed(runnable, 1);
}

private Runnable runnable = new Runnable() {
    public void run() {
        pB.setProgressDrawable(getResources().getDrawable(R.drawable.green));
        pB.invalidate(); // maybe this will even not needed - try to comment out
    }
};
cgh8pdjw

cgh8pdjw3#

使用asynctask类(而不是runnable)。它有一个名为onprogressupdate的方法,可以影响ui(在ui线程中调用)。

6za6bjd0

6za6bjd04#

您应该在asynctask(一个智能回退线程)和progressdialog的帮助下完成这项工作
asynctask允许正确而简单地使用ui线程。此类允许在ui线程上执行后台操作和发布结果,而无需操纵线程和/或处理程序。
异步任务由在后台线程上运行的计算定义,其结果在ui线程上发布。异步任务由3个泛型类型(称为params、progress和result)和4个步骤(称为begin、doinbackground、processprogress和end)定义。
四个步骤
在执行异步任务时,任务将经历4个步骤: onPreExecute() ,在执行任务后立即在ui线程上调用。此步骤通常用于设置任务,例如通过在用户界面中显示进度条。 doInBackground(Params...) ,在onpreexecute()完成执行后立即在后台线程上调用。此步骤用于执行可能需要很长时间的背景计算。异步任务的参数被传递到此步骤。此步骤必须返回计算结果,并将返回到最后一步。此步骤还可以使用publishprogress(progress…)发布一个或多个进度单元。这些值在ui线程的onprogressupdate(progress…)步骤中发布。 onProgressUpdate(Progress...) ,在调用publishprogress(progress…)后在ui线程上调用。执行的时间未定义。此方法用于在后台计算仍在执行时在用户界面中显示任何形式的进度。例如,它可以用来制作进度条的动画或在文本字段中显示日志。 onPostExecute(Result) ,在后台计算完成后在ui线程上调用。背景计算的结果作为参数传递到此步骤。线程规则
要使此类正常工作,必须遵循一些线程规则:
必须在ui线程上创建任务示例。必须在ui线程上调用execute(params…)。不要手动调用onpreexecute()、onpostexecute(result)、doinbackground(params…)、onprogressupdate(progress…)。任务只能执行一次(如果尝试第二次执行,将引发异常)
示例代码
适配器在本例中所做的并不重要,更重要的是要理解您需要使用asynctask来显示进度对话框。

private class PrepareAdapter1 extends AsyncTask<Void,Void,ContactsListCursorAdapter > {
    ProgressDialog dialog;
    @Override
    protected void onPreExecute() {
        dialog = new ProgressDialog(viewContacts.this);
        dialog.setMessage(getString(R.string.please_wait_while_loading));
        dialog.setIndeterminate(true);
        dialog.setCancelable(false);
        dialog.show();
    }
    /* (non-Javadoc)
     * @see android.os.AsyncTask#doInBackground(Params[])
     */
    @Override
    protected ContactsListCursorAdapter doInBackground(Void... params) {
        cur1 = objItem.getContacts();
        startManagingCursor(cur1);

        adapter1 = new ContactsListCursorAdapter (viewContacts.this,
                R.layout.contact_for_listitem, cur1, new String[] {}, new int[] {});

        return adapter1;
    }

    protected void onPostExecute(ContactsListCursorAdapter result) {
        list.setAdapter(result);
        dialog.dismiss();
    }
}
pvabu6sv

pvabu6sv5#

你需要创建一个 Handler 在ui线程中,然后使用它发布或发送来自其他线程的消息以更新ui

iszxjhcz

iszxjhcz6#

如果您不喜欢asynctask,可以使用observer模式。在该示例中,将responsehandler用作活动中的内部类,然后生成一条字符串消息,该消息将设置进度条百分比。。。您需要确保在responsehandler中执行对ui的任何更改,以避免冻结ui,然后您的工作线程(示例中的eventsource)可以执行所需的任务。
我会使用asynctask-tho,但是由于定制的原因,observer模式可能很好,而且它更容易理解。我也不确定这种方式是否被广泛接受或将100%的工作。我正在下载android插件来测试它

nlejzf6q

nlejzf6q7#

根据官方文档的建议,可以使用asynctask处理持续时间小于5ms的工作项。如果你的任务需要更多的时间,那就寻找其他的选择。
handlerthread是 Thread 或者 AsyncTask . 如果您需要从 HandlerThread ,在ui线程上发布消息 Looper ui线程处理程序可以处理ui更新。
示例代码:
安卓:在一个线程吐司

相关问题