不确定的ProgressBar在AsyncTask操作期间未显示

12

我有一个GoogleTranslate.java文件,其中包含一个类GoogleTranslate,它扩展了AsyncTask。这个任务的目的是执行谷歌翻译。

我还有另一个类MyVocab,它允许用户在警报对话框中输入要翻译的单词。因此,在单击警报对话框按钮时,将通过调用GoogleTranslate类将单词翻译为所需语言。然而,当我从MyVocab传递进度条到GoogleTranslate时,它不起作用。当操作正在运行(持续一段可观的时间)时,进度条不显示。我在onPreExecute中将进度条设置为VISIBLE,并在onPostExecute中将其设置为GONE。

我想知道是否因为我将GoogleTranslate和MyVocab放在两个不同的java文件中,因为我看到的大多数示例都是异步类和调用它的类在同一个java文件中。请告诉我是否有任何我做错了导致这个问题的地方。

以下是相关代码:

GoogleTranslate.java

public class GoogleTranslate extends AsyncTask<String, Void, String>{

private ProgressBar mProgressBar;

public GoogleTranslate(ProgressBar progressBar) {
    super();
    mProgressBar = progressBar;
}

@Override
protected void onPreExecute() {
    mProgressBar.setVisibility(View.VISIBLE);
}

@Override
protected void onPostExecute(String s) {
    mProgressBar.setVisibility(View.GONE);
}

@Override
protected String doInBackground(String... params) {
    String vocab = params[0];
    String source = params[1];
    String target = params[2];

    String sourceQuery = "";
    String targetQuery = "&target=" + target;

    // "" means its
    if (!source.equals("Detect Language")) {
        sourceQuery = "&source=" + source;
    }

    try {
        String APIKey = "MY_API_KEY";
        String encodedQuery = URLEncoder.encode(vocab, "UTF-8");
        URL url = new URL("https://www.googleapis.com/language/translate/v2?key=" +
                APIKey +
                "&q=" +
                encodedQuery +
                sourceQuery +
                targetQuery);
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
            StringBuilder stringBuilder = new StringBuilder();
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line).append("\n");
            }
            bufferedReader.close();
            return stringBuilder.toString();
        }
        finally {
            urlConnection.disconnect();
        }
    }
    catch (Exception e) {
        return null;
    }
}

}

来自MyVocab的方法部分:

protected void addVocabAlertDialog(final VocabDbHelper dbHelper, final String category,
                                 final VocabCursorAdapter cursorAdapter) {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("Add Vocab");

    LayoutInflater li = LayoutInflater.from(CategoryItem.this);
    View promptsView = li.inflate(R.layout.alert_dialog_add_vocab, null);
    final EditText vocabInput = (EditText) promptsView.findViewById(R.id.vocabInput);
    final EditText definitionInput = (EditText) promptsView.findViewById(R.id.definitionInput);
    final ProgressBar progressBar = (ProgressBar) promptsView.findViewById(R.id.progressBar);
    builder.setView(promptsView);

    final GoogleTranslate googleTranslate = new GoogleTranslate(progressBar);
    // Set up the buttons
    builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            String vocab = vocabInput.getText().toString();
            String definition = definitionInput.getText().toString();
            dbHelper.insertVocab(category, vocab, definition, 0);
            if (!category.equals(VocabDbContract.CATEGORY_NAME_MY_WORD_BANK)) {
                dbHelper.insertVocab(VocabDbContract.CATEGORY_NAME_MY_WORD_BANK, vocab, definition, 0);
            }
            // Update Cursor
            Cursor cursor = dbHelper.getVocabCursor(category);
            cursorAdapter.changeCursor(cursor);
        }
    });
    final AlertDialog dialog = builder.create();

    dialog.show();

    dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String vocab = vocabInput.getText().toString();

            SharedPreferences sharedPreferences = getSharedPreferences("Translation", MODE_PRIVATE);
            int sourcePos = sharedPreferences.getInt("Source", 0); // 0 is for Detect Language
            int targetPos = sharedPreferences.getInt("Target", 19); // 19 is for English

            String source = LanguageOptions.FROM_LANGUAGE_CODE[sourcePos];
            String target = LanguageOptions.TO_LANGUAGE_CODE[targetPos];

            final AlertDialog.Builder builder = new AlertDialog.Builder(CategoryItem.this);
            builder.setMessage("Network is unavailable. Please try again later.");
            builder.setNegativeButton("OK", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.cancel();
                }
            });
            AlertDialog dialog = builder.create();

            if (isNetworkAvailable()) {
                AsyncTask<String, Void, String> asyncTask = googleTranslate.execute(vocab, source, target);
                try {
                    String translatedJSON = asyncTask.get();
                    JSONParser jsonParser = new JSONParser();
                    String translatedText = jsonParser.parseJSONForTranslation(translatedJSON);
                    definitionInput.setText(translatedText);
                } catch (Exception e) {
                    dialog.show();
                }
            }
            else {
                dialog.show();
            }
        }
    });

}

包含进度条的XML文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Vocab"
    android:id="@+id/vocabInput"
    android:inputType="textAutoComplete"/>

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Definition"
    android:id="@+id/definitionInput"
    android:inputType="textAutoComplete"
    android:layout_below="@+id/vocabInput"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />

<ProgressBar
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:visibility="gone"
    android:indeterminate="true"
    android:id="@+id/progressBar"/>


一个快速(愚蠢)的检查:你的主题颜色是否与进度条背景不同?因为progressBar默认颜色是colorAccent... - Federico De Gioannini
1
我刚刚测试了你的GoogleTranslate类,进度条对我来说完美地工作了。起初我没有看到进度,因为我有一个异常,所以任务立即结束了。为了无论如何看到进度条,我只需在post execute中添加延迟:@Override protected void onPostExecute(String s) { new Handler().postDelayed(new Runnable() { @Override public void run() { mProgressBar.setVisibility(View.GONE); } },3000); }请尝试一下,以排除任务太快的可能性。 - Federico De Gioannini
你好Federico,感谢你的时间!我实际上在模拟器中使用了最慢的互联网连接设置(尝试了两个不同的模拟器),所以操作至少需要3到4秒才能运行。然而,它仍然没有显示任何东西。当该过程运行了那么长时间时,按钮仅保持略微变灰,并且在整个翻译操作期间似乎被按下。 - Charles Li
我刚刚更新了代码,使用GoogleTranslate类构造函数来通过进度条。结果没有任何区别。 - Charles Li
我不确定为什么,但似乎我可以在onClick方法之外直接设置进度条的可见性(仅用于测试),但在其中却不能这样做。 - Charles Li
显示剩余5条评论
6个回答

5

我建议使用 ProgressDialog 替代。

我之前使用 ProgressBar 遇到了类似的问题,即使在我的 AsyncTask 的默认构造函数中以编程方式创建了一个。

public class GoogleTranslate extends AsyncTask<String, Void, String> {
    private ProgressDialog mProgressDialog;
    private Context mContext;

    public GoogleTranslate(Context context) {
        mContext = context;
    }

     @Override
     protected void onPreExecute() {

         mProgressDialog = ProgressDialog.show(
                mContext,
                "Please wait", // Title
                "Translating", // Message
                true           // Indeteriminate flag
         );
     }

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

     @Override
     protected void onPostExecute(String s) {
         if (mProgressDialog != null) {
              mProgressDialog.dismiss();
         }
         ...
     }
 }

像这样调用 AsyncTask

new GoogleTranslate(getActivity() /* or getContext() */).execute(vocab, source, target);

谢谢您的建议!我其实也在考虑这个选项。然而,官方的Android文档说:“避免使用ProgressDialog | Android包含另一个对话框类ProgressDialog,它显示带有进度条的对话框。但是,如果您需要指示加载或不确定的进度,则应遵循进度和活动的设计指南,并在布局中使用ProgressBar。”所以我正在看看是否仍然可以使用ProgressBar,除非没有办法解决它。再次感谢! - Charles Li
1
@Charles Li 嗯,Android文档只是要遵循的指南。 我曾经因为ProgressBar问题卡了3天,直到最后决定使用ProgressDialog(我读了文档,和你现在的想法一样)。我建议你再等几天,如果还找不到解决方案,就用ProgressDialog吧 :) - adhirajsinghchauhan
是的!这也是我想到的!这是我最后一次努力寻找解决方案。哈哈,非常感谢您的意见! - Charles Li

4

谢谢您的建议。但是,当我按照您的建议添加了两行代码后,什么也没有改变。我刚刚发布了包含进度条的警报对话框的xml文件。这是一个圆形进度条(不确定),这就是我没有实现onProgressUpdate的原因。在这种情况下,我是否仍然需要实现onProgressupdate?因为提供的示例我认为是针对确定性进度条的。谢谢! - Charles Li
你在进度条的xml文件中添加了 android:indeterminate="true" 吗? - mehd azizi
我之前没有它,但即使我现在添加了它,也没有任何变化。顺便说一下,使用我的当前xml(无论是否具有indeterminte="true"),在xml中将其默认可见性设置为“visible”将使不确定进度条显示出来,因此问题仅在于控制它出现的时间。感谢您的帮助! - Charles Li
我在思考Java是按值传递,可能我在GoogleTranslate类中设置进度条的方法是不正确的。仍在尝试不同的方法。 - Charles Li

4
尽量避免使用AsyncTask的get()方法,转而使用listener。你应该按照以下方式更新你的代码:
1) 在你的googleTranslate类中添加一个listener:
private Listener listener;

    public interface Listener{
        void onTaskResult(String string);
    }

    public void setListener(Listener listener){
        this.listener = listener;
    }

并在你的onPostExecute中调用它:

 @Override
    protected void onPostExecute(String s) {
        if (listener!=null){ listener.onTaskResult(s); }
                mProgressBar.setVisibility(View.GONE);

    }

2) 更新您的主类,用监听器管理替换get方法,将其替换为:

AsyncTask<String, Void, String> asyncTask = googleTranslate.execute(vocab, source, target);
                try {
                    String translatedJSON = asyncTask.get();
                    JSONParser jsonParser = new JSONParser();
                    String translatedText = jsonParser.parseJSONForTranslation(translatedJSON);
                    definitionInput.setText(translatedText);
                } catch (Exception e) {
                    dialog.show();
                }

使用以下方法:

googleTranslate.setListener(new GoogleTranslate.Listener() {
            @Override
            public void onTaskResult(String string) {
                    String translatedJSON = string;
                    JSONParser jsonParser = new JSONParser();
                    String translatedText = jsonParser.parseJSONForTranslation(translatedJSON);
                    definitionInput.setText(translatedText);
            }
        });
        googleTranslate.execute(vocab, source, target);

我希望你能理解并受益于这些内容。

1
非常感谢你在这段时间里的帮助,Federico!我花了一些时间来理解你的代码,但现在它对我来说是有意义的,并且它可以工作!现在我需要更深入地研究asynctask.get!再次感谢! - Charles Li

3
尝试将ProgressBar作为GoogleTranslate类的构造函数参数传递。

我尝试过了,但还是不行。谢谢! - Charles Li

3
在你的onPreExecute方法中添加进度条,并在onPostExecute中隐藏它。
private class MyAsyncThread extends AsyncTask<Void, Void, String>
{
            @SuppressWarnings("finally")

            @Override
            protected String doInBackground(Void... params) {
                // TODO Auto-generated method stub
                try {

                // your code

                }
                catch (Exception e) {
                    // TODO: handle exception
                }
                finally
                {

                    return "OK";

                }

            }
            @Override
            protected void onPostExecute(String result) {
                // TODO Auto-generated method stub
                super.onPostExecute(result);

               if (progressDialog != null) {
                   progressDialog.dismiss();
                   progressDialog = null;
               }

                        }catch (Exception e) {
                            // TODO: handle exception
                            e.printStackTrace();
                        }
            }


            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                progressDialog = ProgressDialog.show(this, null, "Please wait....");
            }

2

这是因为你正在通过 asyncTask.get() 调用阻塞主线程,因此在 asyncTask 完成之前无法运行任何 UI 操作。

请移除此调用并在其 onPostExecute(String s)onCancelled() 回调中处理 asyncTask 的结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接