【问题标题】:Update UI widget from onPostExecute() of AsyncTask in another project从另一个项目中 AsyncTask 的 onPostExecute() 更新 UI 小部件
【发布时间】:2014-08-13 06:38:16
【问题描述】:

所以,我想在从网站下载并保存在设备文件系统中的 ImageView 中显示图像。图像的下载是通过调用另一个类(在我的一个单独的库项目中)中的方法来完成的。反过来,此方法调用 AsyncTask 在另一个线程中进行下载。在此 AsyncTask 的后期执行中,我想为 ImageView 设置图像。请记住,这个单独的库独立于我的主应用程序,并且对我的 UI 一无所知(我希望保持这种方式)。

我的代码(在片段中)的 UI 部分中有一个方法,用于设置此 ImageView 的图像。我认为最好将此方法传递给检索图像的库方法。这样,当下载完成时, onPostExecute() 可以调用我拥有的这个 UI 方法。我面临的困境是我不希望引用我的 UI/ImageView 的库有任何编译时依赖项。

最后,不是每次调用此 AsyncTask 时我都想在执行后执行任何操作。换句话说,任何后执行逻辑都是完全可选的。

一般流程:

1) 我的片段中的代码调用 MyLib.saveRemoteFile(url, destinationFilename)

2) MyLib.saveRemoteFile() 下载图像并通过线程(通过 AsyncTask)将其保存到文件中

3) 下载并保存图像后,我想使用保存文件中的位图设置 ImageView.setImageBitmap()

我查看了命令模式,但我一直坚持如何在这个特定场景中实现它。对此有什么建议吗?

也许可以使用另一种方法? (没有 MyLib.saveRemoteFile() 对 UI 有编译时依赖项)?

UI片段代码sn-p:

.
boolean wasSaved = MyLib.saveRemoteFile(url, destinationFilename, true)
.
.
.

库代码 sn-p (在不同的库项目中)

public static boolean saveRemoteFile(String url, String filename, boolean overwriteExistingFile)
{
    .
    // code to check if directory exist and creates it if needed, etc, etc...
    .
    .
    .
    new AsyncTask<String, Void, Boolean>() {
        @Override
        protected Boolean doInBackground(String... params)
        {
            // code to download and save image file...
            .
            .
            .
        }

        @Override
        protected void onPostExecute(Boolean result)
        {
            // *** this is where I want to take the ImageView and set its bitmap image.
        }
    }.execute(new String[] {url, filename});

    return retVal;
}

【问题讨论】:

  • 不能在非ui线程中保存吗?
  • 您可以将接口实现为库中的回调方法。
  • @dtheo,保存是在非 UI 线程中完成的。它在 AsyncTask 中。 @Muthu,这就是我最终使用一个简单的侦听器界面所做的事情。谢谢!

标签: java android multithreading android-fragments android-asynctask


【解决方案1】:

设计有缺陷,库应该为您提供观察者设计模式,使用它您可以提交侦听器参考以及下载详细信息。

完成下载后,使用您提供的侦听器的库会通知您下载过程的结果,您可以通过 UI 轻松读取这些结果。

此外,在您的库代码中,saveRemoteFile() 会生成一个异步任务,此处的返回值无关紧要,因为方法不会等到异步任务执行完毕。

根据上述信息可能实现。

    // Interface for bserving
    public interface DownloadListsner{
        public void onSuccess(String uri);
        public void onError(String uri);
    }
    // API for submitting download request
    public void saveRemoteFile(String url, String filename,DownloadListsner listener... ){

        ...
    }

    AsyncTask{
        // Upon finish execution
        onPostExecute(){

// Take action
            listener.onSuccess

            or 

            listener.onError
        }
    }

【讨论】:

  • 谢谢!根据您的建议,我已经实现了一个简单的本土监听器。我将更多地研究 java.util.Observer 类以满足我未来的需求。另外,感谢您指出代码中的返回值问题。
【解决方案2】:

命令模式

您应该更愿意实现Observer pattern,并且您的下载库应该允许其他代码附加侦听器并在某些操作完成/开始/无论何时收到通知。而且由于您只是被告知发生了某事,因此如果您需要,您可以在应用程序的每个部分中对通知做出反应的代码完全不同。

【讨论】:

  • 谢谢,马辛。我将@Techfist 的答案标记为正确。你的也是正确的,但他更详细地介绍了如何为我现有的代码实现这一点。我试图赞成你的回答,但我没有足够的分数来这样做。当我确实有足够的积分时,我会记下回来投票。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多