Java 从非UI线程更新UI方法中的状态

Java 从非UI线程更新UI方法中的状态,java,android,Java,Android,我有一个活动,其中包括一个文本视图,用于显示应用程序的当前状态。除了MainActivity之外,还有一个类用于检查更新,然后根据需要更新应用程序 这是代码的重要部分 public class MainActivity extends AppCompatActivity { private TextView status; @Override protected void onCreate(Bundle savedInstanceState) { su

我有一个
活动
,其中包括一个
文本视图
,用于显示应用程序的当前状态。除了
MainActivity
之外,还有一个类用于检查更新,然后根据需要更新应用程序

这是代码的重要部分

public class MainActivity extends AppCompatActivity {

    private TextView status;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        status  = findViewById(R.id.status);

        new Update().check();
    }

    public void setStatus(String status) {
        this.status.setText(status);
    }
}
如何从
update
类中更新状态
TextView

    public class Update extends Activity {
        public void check(final Context c) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    TextView status = findViewById(R.id.status);
                    status.setText("Checking for updates...");
                }
            });

            // final TextView status = getApplicationContext().findViewById(R.id.status);
            //  status.setText("Checking for updates");

            // Check for updates...

        }

        public class UpdateApp extends AsyncTask<String,Void,Void> {
            private Context context;
            public void setContext(Context contextf){
                context = contextf;
            }

            @Override
            protected Void doInBackground(String... arg0) {

            // Update the app

            }
        }
    }
公共类更新扩展活动{
公共无效检查(最终上下文c){
runOnUiThread(新的Runnable(){
@凌驾
公开募捐{
TextView status=findviewbyd(R.id.status);
status.setText(“检查更新…”);
}
});
//最终文本视图状态=getApplicationContext().findViewById(R.id.status);
//status.setText(“检查更新”);
//检查更新。。。
}
公共类UpdateApp扩展异步任务{
私人语境;
公共void setContext(Context contextf){
上下文=上下文f;
}
@凌驾
受保护的Void doInBackground(字符串…arg0){
//更新应用程序
}
}
}
试图运行
getApplicationContext()。findViewById(R.id.status)
会使应用程序崩溃。当我把它放在一个
尝试
阻止它仍然崩溃应用程序-当我
捕获
一个
可丢弃的
对象时怎么会这样。。。那没有道理


使用
runOnUiThread
应用程序运行,但状态未更新。

UpdateApp
AsynTask放入新文件

public class MainActivity extends AppCompatActivity {

    private TextView status;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        status  = findViewById(R.id.status);

        new UpdateApp(status).execute();
    }
}
UpdateApp.java

public class UpdateApp extends AsyncTask<String,Void,Void> {
    private TextView status;
    public UpdateApp(TextView status){
        this.status = status;
    }
    @Override
    protected void onPostExecute(String result) {
        status.setText("Update complete");
    }

    @Override
    protected void onPreExecute() {
         status.setText("Checking for updates...");
    }
    @Override
    protected Void doInBackground(String... arg0) {

        // Update the app

    }
}
公共类UpdateApp扩展异步任务{
私有文本视图状态;
公共更新PP(文本视图状态){
这个状态=状态;
}
@凌驾
受保护的void onPostExecute(字符串结果){
status.setText(“更新完成”);
}
@凌驾
受保护的void onPreExecute(){
status.setText(“检查更新…”);
}
@凌驾
受保护的Void doInBackground(字符串…arg0){
//更新应用程序
}
}

只需在MainActivity中复制您的
UpdateApp
类,即可访问您的
状态视图

如果您希望您的
UpdateApp
类位于不同的文件中(我建议使用该文件来分离类的责任),您需要一个回调:一个对活动的引用,以从
异步任务
类更新
状态
视图。您可以使用
接口
。看看这个例子

MainActivity.java

public class MainActivity extends AppCompatActivity implements CallbackInterface {

    private TextView status;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        status  = findViewById(R.id.status);
        new LoaderClass(this).execute();
    }

    @Override
    public void setStatusText(String text) {
        status.setText(text);
    }
}
CallbackInterface.java

public interface CallbackInterface {
    void setStatusText(String text);
}
LoaderClass.java

public class LoaderClass extends AsyncTask<String, Void, Void> {
    private CallbackInterface callbackInterface;

    public LoaderClass(CallbackInterface callback) {
        callbackInterface = callback;
    }


    @Override
    protected Void doInBackground(String... arg0) {
        callbackInterface.setStatusText("Loaded text");
        return null;
    }
}
公共类装入器类扩展异步任务{
专用回调接口回调接口;
公共LoaderClass(回调接口回调){
callbackInterface=callback;
}
@凌驾
受保护的Void doInBackground(字符串…arg0){
callbackInterface.setStatusText(“加载的文本”);
返回null;
}
}

如果您正在参加任何活动,可以使用runonUIthread()如-


将更新代码放在一个单独的类中的原因是为了使代码将来可用于不同的应用程序。然后将异步任务放在一个新文件中。让我更新并在旋转后发生内存泄漏检查更新的当前代码将显示一个
警报对话框
,以便用户可以选择是否安装更新。
onPreExecute()
方法是否可以访问UI以显示此选项?感谢@IgorBykov指出内存泄漏。我想我可以看到它的原因,但是我会问另一个问题来检查我的理解,并且我能够避免它。runOnMainThread()包含在原始代码中,但没有更新UIA。我是对的,
接口
是一个单独的文件,就像
是一个单独的文件一样?是的!我在代码前附上了文件名。有3个文件:MainActivity、CallbackInterface(接口)和LoaderClass(异步任务类)
runOnUiThread(new Runnable() {
        @Override
        public void run () {

          // do your magic here

        }
    });