【问题标题】:Loading a layout using ASyncTask in Android在 Android 中使用 ASyncTask 加载布局
【发布时间】:2012-11-08 02:26:45
【问题描述】:

我有一个应用程序加载一个对话框,其中包含对话框的 XML 布局中指定的一些图像。我已经阅读了很多关于在 Android 中使用图像并注意 VM 预算的内容,因此我相信任何可能占用大量内存的图像处理都应该在主线程之外处理。话虽如此,我想知道使用 ASyncTask 从 UI 线程加载整个布局是否明智。我有一个工作代码,但我无法通过一些谷歌搜索来确定这是否是一种好习惯。这是下面的代码。

这是当用户按下按钮加载对话框时触发的 case 语句。

case R.id.showDialog:

    vibrator.vibrate(vibrateMilis);

    mDialog = new Dialog(getActivity(), R.style.CustomDialog);

    new LoadLayout().execute("");

break;

这里是 ASyncTask

private class LoadLayout extends AsyncTask<String, Void, String> 
{

    ProgressDialog progressDialog;

        @Override
        protected String doInBackground(String... params) 
        {

            mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            mDialog.setContentView(R.layout.dialog_layout);
            mDialog.setCancelable(true);

            return null;
        }

        @Override
        protected void onPostExecute(String result)
        {

            progressDialog.cancel();

            mDialog.show();

        }

        @Override
        protected void onPreExecute() 
        {

            progressDialog = new ProgressDialog(
                    getActivity());
            progressDialog.setMessage("Loading...");
            progressDialog.setCancelable(false);
            progressDialog.show();

        }

        @Override
        protected void onProgressUpdate(Void... values) 
        {

            // Do nothing

        }

}

所以这段代码有效,但我的问题是这个。这被认为是好的做法吗?我的口味似乎有点hacky。我没有通过多次 Google 搜索发现这一点,所以这就是我有点担心的原因。我的意思是,如果这是一种好的做法,它会被记录在某个地方吗?

感谢您的任何意见。

【问题讨论】:

  • 看我的回答。我已经用代码更新了它。

标签: android android-layout android-asynctask android-xml android-dialog


【解决方案1】:

您是否参考了 android 开发者网站。你的方法是错误的。如需更多指导,请参阅Vogella 文档。它很好地解释了 AsyncTask。

另请参阅下面的 AsyncTask 示例代码。

    // The definition of our task class
   private class PostTask extends AsyncTask<String, Integer, String> {
   @Override
   protected void onPreExecute() {
      super.onPreExecute();
      displayProgressBar("Downloading...");
   }

   @Override
   protected String doInBackground(String... params) {
      String url=params[0];

      // Dummy code
      for (int i = 0; i <= 100; i += 5) {
        try {
          Thread.sleep(50);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
         publishProgress(i);
      }
      return "All Done!";
   }

   @Override
   protected void onProgressUpdate(Integer... values) {
      super.onProgressUpdate(values);
      updateProgressBar(values[0]);
   }

   @Override
   protected void onPostExecute(String result) {
      super.onPostExecute(result);
      dismissProgressBar();
   }
   }

希望对你有很大帮助。

享受编码... :)

【讨论】:

  • IDroid 非常感谢您的意见。我了解 ASyncTask 的工作原理,但我不明白为什么我不能在后台线程上加载布局并在主线程上用它更新 UI。就像我说的代码工作正常我只是想知道为什么它不是好的做法。我会说,由于使用此代码,我在模拟器上没有 OutOfMemory 异常(对话框包含许多图像),因为我没有使用 ASyncTask
  • UI Thread 和 android 主线程是分开的东西。一旦主线程运行,您就无法更改 UI。因此,在 AsyncTask 的 doBackground 过程中,会发生任何后台 prosecc,因此当时您无法使用 android UI。后台进程完成后,只有您可以工作或更改 UI。希望你能明白这一点。有关 AsyncTask 线程的更多信息,另请参阅 (developer.android.com/reference/android/os/AsyncTask.html)。
  • @John P.:谢谢伙计。您也可以对其进行投票,以便对其他人提供更多帮助。
【解决方案2】:

我认为你做错了,因为:

首先,当调用doInBackground()方法时,它会在其他线程中,你只能在主线程中改变UI元素。

其次,显示一个对话框不浪费时间,你可以在onPreExecute()或onPostExecute(String result)中调用它,然后在doInBackground()中做一些让用户等待的动作,比如从网络或数据库中获取数据。

【讨论】:

  • 感谢您的回复。我知道 doInBackground() 无法更新 UI 元素,但我想知道这段代码是如何工作的?我什至在布局中有按钮,从来没有 NullPointer 异常,我只调用 mDialog.setContentView(R.layout.dialog_layout);来自 ASyncTask
  • 其实,我在progressDialog.cancel()之后在onPostExecute()中不t undstand why you have two dialog for?If you want to show get data or somewhat from doInBackground() for mDialog , why you didnt调用mDialog.show()?
  • progressDialog 显示 ASyncTask 正在运行,而 mDialog 正在加载。在 PostExecute 中,我确实调用了 mDialog.show() 我只是在发布此内容时忘记添加它。它现在就在那里。
  • 我认为这行得通的原因是您在后台线程中创建了对象,但是直到您使用 onPostExecute() 返回主线程时才使用它更新 UI。
  • 敢于对我有意义。但是,如果我在后台线程中创建对象并使用主线程更新 UI,那么这个实现怎么错了?顺便说一句,这完全是出于好奇=]
【解决方案3】:

您不能在后台线程中加载整个布局(请注意AsyncTask.postExecute() 在主线程上执行)。因为所有的 UI 组件都应该只从 Main Thread(也称为 UI 线程)修改。您可以使用后台线程来收集显示 UI 所需的信息。

【讨论】:

  • 这就是我想要做的。你知道这是怎么做的吗?
  • AsyncTask 非常适合它。例如,您想在后台线程中从网络资源加载Bitmap 并将其传递给UI 线程,您可以拥有AsyncTask&lt;void, void, Bitmap&gt; 并在doInBackground() 方法中返回Bitmap。然后框架将 Bitmap 传递给在主线程上调用的 onPostExecute(Bitmap bitmap) 方法。现在您可以将 Bitmap 设置为 ImageView
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多