如何使用 AsyncTask 更新全局变量

Posted

技术标签:

【中文标题】如何使用 AsyncTask 更新全局变量【英文标题】:How to use AsyncTask to update a global variable 【发布时间】:2014-07-20 16:42:35 【问题描述】:

我想要做什么:我正在使用自定义“位置”适配器将行放入ListView。我正在尝试将Bitmap 添加到 ListView 的一行中。此位图来自 URL。所以,我有一个全局变量public static Bitmap bitmap 并想使用 AsyncTask 更新这个变量。这是我的代码:

            try 
                String s = "";
                JSONArray jArray = new JSONArray(result);

                for (int i = 0; i < jArray.length(); i++) 
                    final JSONObject json = jArray.getJSONObject(i);
                    runOnUiThread(new Runnable() 
                        @Override
                        public void run() 

                            try 

                                //here I am calling my new task and giving it the ID to find the image
                                BitmapWorkerTask myTask = new BitmapWorkerTask(json.getInt("ID"));
                                myTask.execute();
                                adapter.add(new Location(bitmap, json
                                        .getString("PlaceTitle"), json
                                        .getString("PlaceDetails"), json
                                        .getString("PlaceDistance"), json
                                        .getString("PlaceUpdatedTime")));

                                bitmap = null;
                             catch (JSONException e) 
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            

                        
                    );

                

             catch (Exception e) 
                // TODO: handle exception
                Log.e("log_tag", "Error Parsing Data " + e.toString());
            

这是我的异步任务

class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> 
    private int photoID = 0;

    public BitmapWorkerTask(int photoID) 
        // Use a WeakReference to ensure the ImageView can be garbage collected
        this.photoID = photoID;
    

    // Decode image in background.
    @Override
    protected Bitmap doInBackground(Integer... params) 
        String initialURL = "http://afs.spotcontent.com/img/Places/Icons/";
        final String updatedURL = initialURL + photoID + ".jpg";
        Bitmap bitmap2 = null;

        try 
            bitmap2 = BitmapFactory.decodeStream((InputStream) new URL(
                    updatedURL).getContent());

         catch (MalformedURLException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
        

        return bitmap2;
    

    // Once complete, see if ImageView is still around and set bitmap.
    @Override
    protected void onPostExecute(Bitmap bitmap2) 
        bitmap = bitmap2;
    

因此,对于每次迭代,我都会为 AsyncTask 提供一个用于查找图像的 ID,然后(我希望)应该更新传递给适配器的全局位图。当我运行我的应用程序时,每个列表的图片都是空的。关于我做错了什么有什么想法吗?

【问题讨论】:

onPostExecute 是否为bitmap2 返回正确的位图?另外,onPostExecute 中的 bitmap 变量不应该像 ClassName.bitmap 那样静态访问吗? 我假设它正在为 bitmap2 发回正确的位图。 doInBackground 方法检索 bitmap2,然后 onPostExecute 设置全局 bitmap = bitmap2。对吗? 我知道doInBackground中位图的检索是成功的,因为我已经在AsyncTask之外尝试过了 好吧,假设我们不知道。在 doInBackground 上进行调试或将System.out.println() 添加到 doInBackground 中的异常中,以查看那里是否发生了任何事情。然后继续前进。 正在检索位图。我设置了一个 imageView = 位图,它起作用了。出于某种原因,它没有更新全局位图变量 【参考方案1】:

考虑以下可能的命令执行顺序(记住任务在后台运行,因此顺序是不确定的):

    myTask.execute() BitmapWorkerTask.doInBackground() adapter.Add(new Location(bitmap, ....... BitmapWorkerTask.onPostExecute()

当您在步骤 3 中创建 Location() 对象时,传递的“位图”对象是全局对象指针。它的值还不是有效的,因为 onPostExecute() 还没有被调用。所以 Location 对象是用非位图对象创建的。在第 4 步,当最终检索到位图时,全局对象指针的值已更改(正确),但这不会影响已在第 2 步中传递给 Location 的(空)位图对象......这就是为什么你在您的视图中看不到位图。

您可以做的是向 BitmapWorkerTask 构造函数传递一个附加参数:您可以传递 Location 对象(或底层位图)。然后,您可以从 onPostExecute() 使用检索到的位图更新该位置/位图对象。这里不需要全局变量。

【讨论】:

这行得通。非常感谢,我不知道为什么这个解决方案从我身边溜走了。 +1!

以上是关于如何使用 AsyncTask 更新全局变量的主要内容,如果未能解决你的问题,请参考以下文章

如何在python中更新全局变量

故事书:如何根据全局变量更新 i18 语言环境

(ActionScript 3.0)我的函数没有通过按钮事件更新全局变量

如何取消设置全局变量。

如何避免在递归中使用全局/类级别变量?

从 jQuery 事件更新全局变量