AsyncTask 不从 postexecute 更新 UI

Posted

技术标签:

【中文标题】AsyncTask 不从 postexecute 更新 UI【英文标题】:AsyncTask not updating UI from postexecute 【发布时间】:2021-04-04 20:34:06 【问题描述】:

在应用 statrs 之后,我有 2 个 AsyncTask 在后台运行。第一个是获取位置,完成后,它会调用另一个任务。第二个任务完成后,它应该在 postexecute 中更新 UI,但它没有。 它应该用数据填充recyclerview,隐藏加载图标并显示recyclerview。

    private FusedLocationProviderClient fusedLocationClient;
    Location location;
    RecyclerView recV;

    @Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    findViewById(R.id.loading).setVisibility(View.VISIBLE);

    recV = findViewById(R.id.rv);
    recV.setLayoutManager(new LinearLayoutManager(MainActivity.this));


    new getLocation().execute(); //the first task gets called here


这是第一个异步任务请求位置:

class getLocation extends AsyncTask<String, Boolean, Boolean> 
    @Override
    protected Boolean doInBackground(String... params) 
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(MainActivity.this);

        if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) 
        CancellationTokenSource cancellationSource = new CancellationTokenSource();
        fusedLocationClient.getCurrentLocation(LocationRequest.PRIORITY_HIGH_ACCURACY, cancellationSource.getToken())
                .addOnSuccessListener(MainActivity.this, new OnSuccessListener<Location>() 
                    @Override
                    public void onSuccess(Location loc) 
                        location = loc;

                        publishProgress(true);
                    
                ).addOnFailureListener(MainActivity.this, new OnFailureListener() 
            @Override
            public void onFailure(@NonNull Exception e) 
                e.printStackTrace();
                publishProgress(true);
            
        );

        while(true)
            if(location != null)
                return true;
        
    

    @Override
    protected void onPostExecute(Boolean result) 
        if(result)
            new getData().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);  //Second task called here

            //Updating the UI here doesn't work

        
    

在此处编辑 UI 上的任何内容都无法正常工作。它被调用,登录到控制台工作,但修改 UI 在这里没有做任何事情。

第二个任务也会发生同样的事情。

runOnUiThread 也不做任何事情。

class getData extends AsyncTask<String, Boolean, Boolean> 
    @Override
    protected Boolean doInBackground(String... params) ...
    
    @Override
    protected void onPostExecute(Boolean result) 
        Log.d(TAG, "this gets displayed in the logcat");
        RecyclerView_Adapter adapter = new RecyclerView_Adapter(routes);
        recV.setAdapter(adapter);
        findViewById(R.id.loading).setVisibility(View.GONE);
        findViewById(R.id.rv).setVisibility(View.VISIBLE);
        findViewById(R.id.rvui).setVisibility(View.VISIBLE);

        //But these UI tasks just don't do anything

这段代码有什么问题? 任何帮助表示赞赏!

【问题讨论】:

将该位置代码放在异步任务中是没有意义的。不用就行了。 【参考方案1】:

这段代码太可怕了。如果 getCurrentLocation 返回 null (它可以),您的循环将永远不会退出,因为位置永远不会改变 - 它始终为 null 或始终不为 null。很可能你没有得到任何位置,因此永远循环。由于所有 AsyncTask 共享一个线程,这将阻止您应用中的所有异步任务。

删除循环,将其替换为 return return location != null。如果位置为空,请确保 onPostExecute 中的任何代码都可以处理它。

【讨论】:

以上是关于AsyncTask 不从 postexecute 更新 UI的主要内容,如果未能解决你的问题,请参考以下文章

向异步任务发送意图

带有进度条的Firebase数据库

带有进度条的 Firebase 数据库

Handler线程中如何做横向数据

如何为单独的 TextView 设置单独的进度条

AsyncTask - 等待其他 Asynctask 的执行