如何正确实现ProgressDialog以便在后台调用耗时的方法?

时间:2010-10-04 21:01:54

标签: java android

我使用BaseAdapter显示对象列表。从服务器获取此对象。 BaseAdapter的getView()方法如下:

/* (non-Javadoc)
         * @see android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)
         */
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            LinearLayout content = (LinearLayout) View.inflate(lexs, R.layout.favorite_item, null);

            LinearLayout paragraphView = new LinearLayout(lexs); 
            paragraphView.setBackgroundColor(Color.RED);
            paragraphView.setGravity(Gravity.CENTER_VERTICAL);
            paragraphView.setOrientation(LinearLayout.HORIZONTAL);

            ImageView img = new ImageView(lexs);
            img.setImageResource(R.drawable.down);
            paragraphView.addView(img);
            img.setPadding(0, 0, 5, 0);
            img.setOnClickListener(new WorkspaceOnClickListener(position));

            TextView text = new TextView(lexs);
            text.setTextColor(Color.WHITE);
            text.setText(favorites.get(position).getParentChapter().getBook().getName() + ": §" + favorites.get(position).getName());
            text.setOnClickListener(new ParagraphOnClickListener(position));

            DisplayMetrics metrics = new DisplayMetrics();
            lexs.getWindowManager().getDefaultDisplay().getMetrics(metrics);
            int maxWidth = metrics.widthPixels - 100;

            text.setMaxWidth(maxWidth);
            text.setMinWidth(maxWidth);
            paragraphView.addView(text);

            ImageView imgClose = new ImageView(lexs);
            imgClose.setMinimumHeight(30);
            imgClose.setMinimumWidth(30);
            imgClose.setImageResource(R.drawable.close);
            imgClose.setPadding(5, 0, 0, 0);
            paragraphView.addView(imgClose);
            imgClose.setOnClickListener(new CloseListener(position));

            content.addView(paragraphView);
            content.setPadding(0, 0, 0, 10);

            if (favorites.get(position).isExpanded()) {
                LinearLayout textLayer = new LinearLayout(lexs);
                textLayer.setBackgroundColor(Color.rgb(214, 214, 214));

                LinearLayout left = new LinearLayout(lexs);
                left.setOrientation(LinearLayout.VERTICAL);

                ImageView moveUp = new ImageView(lexs);
                moveUp.setImageResource(R.drawable.move_up);
                moveUp.setOnClickListener(new MoveListener(UP, position));
                moveUp.setPadding(0, 0, 0, 10);
                left.addView(moveUp);

                ImageView moveDown = new ImageView(lexs);
                moveDown.setImageResource(R.drawable.move_down);
                moveDown.setOnClickListener(new MoveListener(DOWN, position));
                left.addView(moveDown);

                TextView paragraphText = new TextView(lexs);
                paragraphText.setText(favorites.get(position).getText());
                paragraphText.setTextColor(Color.BLACK);

                LinearLayout right = new LinearLayout(lexs);
                right.setOrientation(LinearLayout.HORIZONTAL);
                right.addView(paragraphText);

                textLayer.addView(left);
                textLayer.addView(right);
                content.addView(textLayer);

                img.setImageResource(R.drawable.up);
            }

            return content;
        }

    }

所以我希望在后台调用整个方法,并在执行方法时显示ProgresDialog。我通过以下方式定义了ProgressDialog:

public class LoadingInformation {

    private static ProgressDialog progressDialog;

    public static void showProgressInformation(Context view) {

        progressDialog = ProgressDialog.show(view, "Please wait...", "Doing Extreme Calculations...", true);
        System.out.println("Start Loading Screen");

    }

    public static void stopShowingProgressInformation() {

        Handler handler=new Handler();
        handler.post(new Runnable(){public void run(){progressDialog.dismiss();}});
        System.out.println("Stop Loading Screen");

    }

}

但问题是,我不知道如何正确实现调用。我试图替换所有行:

adapter.notifyDataSetChanged();

使用以下代码:

public void updateFavoriteList() {

        LoadingInformation.showProgressInformation(lexs);

        new Thread() {

            public void run() {

                lexs.runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        adapter.notifyDataSetChanged();
                        LoadingInformation.stopShowingProgressInformation();
                    }

                });



            }

            }.start();


    }

但遗憾的是,这并不像预期的那样有效。有人提示如何做到这一点吗?

2 个答案:

答案 0 :(得分:1)

适配器的 getView()方法不负责下载列表中的内容,它所做的只是构建 ListView 中显示的当前行。 getView()与从网络资源实际下载数据没有任何关系,这是您不想使用 ProgressDialog 的地方。

当您实例化适配器(未在代码中显示)时,您传递了希望 BaseAdapter 填充 ListView 的数据。数据已经下载并简单地传递给适配器,或者适配器本身也在构造函数中。

如果您不想更改 ListView 的数据集,则必须创建一些setter方法或在适配器中使用一种方法自动刷新网络中的数据集。但无论如何,这是您希望显示 ProgressDialog 的地方,而不是在 getView()方法设置 ListView 行时。

P.S。我给出的另一个建议是使用传递给 getView() convertView 参数。如果你有一个大的列表,它会大大提高你的列表的性能。在Google I / O 2009或2010演讲中查看Romain Guy关于 ListView 的演示文稿。


编辑:

所以“favorties”是ListView的数据数组(或List等)。您最有可能通过构造函数参数将“收藏夹”数据传递给适配器。此时数据已经存在于适配器中,或者您正在传递网络位置,因此适配器可以获取数据并将其显示在ListView中。

为简单起见,假设您将一些字符串数据下载到String数组中,然后再将其传递给适配器。每个元素都包含一个字符串,该字符串将通过TextView显示在ListView中。您将该数组传递给适配器,它使用getView()方法中的逻辑处理格式化ListView。

现在,当您下载数据以填充ListView时,您希望显示ProgressDialog以让用户知道正在发生的事情。就像有些人已经说过的那样,你会用AsyncTask来完成这个。 AsyncTask允许您在实际下载onPreExecute()中的数据时通过doInBackground()显示ProgressDialog并删除onPostExecute()中的对话框。

我希望这是有道理的。

答案 1 :(得分:1)

应该使用AsyncTask处理耗时的任务。 阅读https://developer.android.com/resources/articles/painless-threading.html

它已被添加到Android框架中,以帮助您完成这些耗时并更新进度对话框,而无需自己编写任务和处理程序的样板。