java - 从静态 AsyncTask 方法内部访问 Android UI 元素

标签 java android android-asynctask

所以我正在尝试创建一个通过 ssh 连接同步文件的应用程序。 ssh 连接作为 AsyncTask 启动,我希望它在 onPostExecute 方法内设置 UI 元素的文本,但似乎无法在其中声明或使用必要的变量。

public class MainActivity extends AppCompatActivity {

    public TextView infoView = (TextView) findViewById(R.id.infoView);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new sshConnectTask().execute();
    }

    static class sshConnectTask extends AsyncTask<Void, Void, Void> {

        protected Void doInBackground(Void...params){
            /*STUFF*/
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            infoView.setText("ASD");
        }
    }
}

基本上我想在 onPostExecute 方法中调用 infoView.setText() 。

更新 Discord 上有人帮我解决了这个问题:

  1. setContentView 必须在 findViewByID 之前调用;否则 findViewById 只是返回 mull

  2. infoView 变量可以像这样传递给 SSHConnectTask

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView infoView = (TextView) findViewById(R.id.infoView);
        new SSHConnectTask(infoView).execute();
    }
    
  3. 那么 SSHConnectTask 必须进行调整

    static class SSHConnectTask extends AsyncTask<Void, Void, Void> {
        private TextView display;
    
        public SSHConnectTask(TextView display){
            this.display = display;
        }
    

之后,可以在 onPostExecute 中设置 infoViews 文本

protected void onPostExecute(Void aVoid) {
    super.onPostExecute(aVoid);
    display.setText("TEST");

最佳答案

在调用异步代码时使用 Wea​​kReference 是一种黑客行为,您应该做的是使用去年(2017 年)发布的 Android 架构组件,它可以让您简化此类事情。

因此,您有一个观察 View 模型中的数据的 Activity :

public class MainActivity extends AppCompatActivity {
    private TextView infoView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        infoView = findViewById(R.id.infoView);
        MainViewModel mainViewModel = ViewModelProviders.of(this).get(MainViewModel.class);
        mainViewModel.infoText.observe(this, (text) -> {
            infoView.setText(text);
        });
    }
}

并且您应该创建一个 ViewModel,其中在存储在 ViewModel 中的 LiveData 内处理此类连接:

public class MainViewModel extends ViewModel {
    LiveData<String> infoText = new InfoTextLiveData();

    public MainViewModel() {
    }
}

并且您的 LiveData 应该知道如何获取数据:

public class InfoTextLiveData extends MutableLiveData<String> {
    @Override
    protected void onActive() {
        new SshConnectTask().execute(); // optionally, you could `cancel()` the asyncTask in `onInactive()`
    }

    class SshConnectTask extends AsyncTask<Void, Void, Void> {
        protected Void doInBackground(Void...params){
            /*STUFF*/
            postValue("ASD");
            return null;
        }
    }
}
<小时/>

为此,您必须添加 AAC 依赖项:

allprojects {
    repositories {
        jcenter()
        google()
    }
}

implementation "android.arch.lifecycle:extensions:1.1.1"
annotationProcessor "android.arch.lifecycle:compiler:1.1.1"
<小时/>

有关更多信息,请参阅指南:

https://developer.android.com/jetpack/docs/guide

关于java - 从静态 AsyncTask 方法内部访问 Android UI 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50395053/

相关文章:

java - 如何使用 java.time 从带有年和周的字符串中解析日期

java - 在类的构造函数中完成类的主要工作有什么问题吗?

android - 如何在奥利奥中启动后台服务?

java - 将图像从一个 ImageButton 传输到另一个

android - setDataSourceFD 失败。 : status=0x80000000 on playing aac file on Samsung phones

java - 变量赋值和循环

java - java.math.MathContext 的使用

Android 异步任务减慢了我的 UI 线程

java - 等待多个 AsyncTask 完成

java - Android AsyncTask 卡住了