Android 异步任务进度条 onProgressUpdate

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25232343/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 09:15:43  来源:igfitidea点击:

Android Async Task Progress Bar onProgressUpdate

androidandroid-asynctask

提问by André Martinho

I am a new programmer. I have seen lots of tutorials but can't understand what is wrong. I am trying to create a ProgressBar from an Async Task. However it always crashes my application.

我是一个新程序员。我看过很多教程,但不明白什么是错的。我正在尝试从异步任务创建一个 ProgressBar。但是它总是使我的应用程序崩溃。

Here is the "main" app:

这是“主要”应用程序:

package pt.flag.ensemble;

import java.util.Random;

import pt.flag.ensemble.task.AsyncTaskBar;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.Toast;

public class Intervals extends Activity {

    private static Intervals instance;
    private Context context;
    private String answer;
    int right_question;
    int wrong_question;
    int randomInt2;
    public ProgressBar progressBar;




    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_intervals);

        // initializing the sounds
        final MediaPlayer sound1 = MediaPlayer.create(Intervals.this,
                R.raw.maj2);
        final MediaPlayer sound2 = MediaPlayer.create(Intervals.this,
                R.raw.maj3);
        final MediaPlayer sound3 = MediaPlayer.create(Intervals.this,
                R.raw.maj4);

        //ProgressBar
        instance=this;
        ProgressBar progressBar = (ProgressBar) findViewById(R.id.Progressbar);
        progressBar.setProgress(0);


        // Play Methods
        final ImageButton Play = (ImageButton) findViewById(R.id.Play);
        Play.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                new AsyncTaskBar().execute();
                Play.setEnabled(false);
                // generate random number
                Random randomGenerator = new Random();
                int randomInt = randomGenerator.nextInt(3) + 1;
                randomInt2 = randomInt;



                // picking the right sound to play
                    switch (randomInt) {
                    case 1:
                        sound1.start();
                        answer = "M2";
                        break;
                    case 2:
                        sound2.start();
                        answer = "M3";
                        break;
                    case 3:
                        sound3.start();
                        answer = "P4";
                        break;
                    }

            }
        });

        //Audio Repeat Methods
        Button Repeat = (Button) findViewById(R.id.Repeat);
        Repeat.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {



                    // picking the right sound to play
                    switch (randomInt2) {
                    case 1:
                        sound1.start();
                        new AsyncTaskBar().execute();
                        answer = "M2";
                        break;
                    case 2:
                        sound2.start();
                        new AsyncTaskBar().execute();
                        answer = "M3";
                        break;
                    case 3:
                        sound3.start();
                        new AsyncTaskBar().execute();
                        answer = "P4";
                        break;
                    }


            }
        });
    }

    //Answering Methods
    public void buttonClicked2(View view) {
        Button clickedButton = (Button) view;
        if (clickedButton.getText().toString().equals(answer)) {
            Toast.makeText(Intervals.this, "You are Right!", Toast.LENGTH_LONG)
                    .show();

            right_question = right_question + 1;


            final ImageButton Play = (ImageButton) findViewById(R.id.Play);
            Play.setEnabled(true);

            // Passing results through
            SharedPreferences sharedPref = getSharedPreferences(
                    "INTERVALRIGHTS", Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = sharedPref.edit();
            editor.putInt("SCORE", right_question);
            editor.commit();

        } else {
            Toast.makeText(Intervals.this, "You are Wrong!", Toast.LENGTH_LONG)
                    .show();

            wrong_question = wrong_question + 1;

            // Passing results through
            SharedPreferences sharedPref02 = getSharedPreferences(
                    "INTERVALWRONGS", Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = sharedPref02.edit();
            editor.putInt("SCORE02", wrong_question);
            editor.commit();

        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.intervals, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        switch (item.getItemId()) {
        case R.id.action_settings:
            Intent intent = new Intent(Intervals.this, IntervalResults.class);
            startActivity(intent);
            break;
        default:
            return super.onOptionsItemSelected(item);
        }
        return true;
    }

        public static Intervals getApp() { return instance; }
}

Here is the AsyncTask class

这是 AsyncTask 类

package pt.flag.eventapp.task;

import pt.flag.eventapp.Main;
import android.os.AsyncTask;
import android.os.SystemClock;
import android.widget.Toast;

public class ShowDialogAsyncTask extends AsyncTask<Void, Integer, Void> {
    int progress_status;

    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        super.onPreExecute();
        //Toast.makeText(Main.getApp(),"Invoke on PreExecute()", Toast.LENGTH_SHORT).show();
        progress_status = 0 ;
        //Main.getApp().txt_percentage.setText("downloading 0%");
    }

    @Override
    protected Void doInBackground(Void... params) {
        while (progress_status < 100){
            progress_status +=2;
            publishProgress(progress_status);
            SystemClock.sleep(300);
        }
        return null;
    }
    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        //Main.getApp().progressBar.setProgress(values[0]);
        //Main.getApp().txt_percentage.setText("downloading" + values[0] + "%");
}
    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        //Toast.makeText(Main.getApp(), "Invoke onPostExecute()", Toast.LENGTH_SHORT).show();
        //Main.getApp().txt_percentage.setText("download complete");
    }
}

Here is the Log:

这是日志:

08-10 20:38:11.081: E/AndroidRuntime(21441): FATAL EXCEPTION: main
08-10 20:38:11.081: E/AndroidRuntime(21441): java.lang.NullPointerException
08-10 20:38:11.081: E/AndroidRuntime(21441):    at pt.flag.ensemble.task.AsyncTaskBar.onProgressUpdate(AsyncTaskBar.java:34)
08-10 20:38:11.081: E/AndroidRuntime(21441):    at pt.flag.ensemble.task.AsyncTaskBar.onProgressUpdate(AsyncTaskBar.java:1)
08-10 20:38:11.081: E/AndroidRuntime(21441):    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:618)
08-10 20:38:11.081: E/AndroidRuntime(21441):    at android.os.Handler.dispatchMessage(Handler.java:99)
08-10 20:38:11.081: E/AndroidRuntime(21441):    at android.os.Looper.loop(Looper.java:156)
08-10 20:38:11.081: E/AndroidRuntime(21441):    at android.app.ActivityThread.main(ActivityThread.java:4977)
08-10 20:38:11.081: E/AndroidRuntime(21441):    at java.lang.reflect.Method.invokeNative(Native Method)
08-10 20:38:11.081: E/AndroidRuntime(21441):    at java.lang.reflect.Method.invoke(Method.java:511)
08-10 20:38:11.081: E/AndroidRuntime(21441):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
08-10 20:38:11.081: E/AndroidRuntime(21441):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
08-10 20:38:11.081: E/AndroidRuntime(21441):    at dalvik.system.NativeStart.main(Native Method)

If I am correct, the log seems to indicate an error in line 34 at the AsyncTask class, which is "Intervals.getApp().progressBar.setProgress(values[0]);" I just don't know why...

如果我是对的,日志似乎在 AsyncTask 类的第 34 行中指出了一个错误,即“Intervals.getApp().progressBar.setProgress(values[0]);” 我只是不知道为什么...

Also, here is my xml file

另外,这是我的 xml 文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <ImageButton
        android:id="@+id/Play"
        android:contentDescription="@string/hello_world"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_launcher"
        android:layout_marginTop="50dp"
        android:layout_marginLeft="50dp" />

    <Button
        android:id="@+id/Repeat"
        android:contentDescription="@string/hello_world"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Repeat"
        android:layout_marginTop ="50dp"
        android:layout_toRightOf="@+id/Play"
        android:layout_marginLeft="25dp" />

      <ProgressBar
        android:id="@+id/Progressbar"
        style="@android:style/Widget.ProgressBar.Horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="test"
        android:layout_marginTop="20dp"
        android:layout_below="@+id/Play" />

    <Button
        android:id="@+id/Octave_Button"
        android:layout_width="52dp"
        android:layout_height="80dp"
        android:layout_marginLeft="5dp"
        android:layout_below="@+id/Progressbar"
        android:onClick="buttonClicked2"
        android:layout_marginTop="100dp" 
        android:text="@string/octave" />

    <Button
        android:id="@+id/min2_Button"
        android:layout_width="52dp"
        android:layout_height="80dp"
        android:layout_below="@+id/Progressbar"
        android:onClick="buttonClicked2"
        android:layout_marginTop="100dp" 
        android:layout_toRightOf="@+id/Octave_Button"
        android:text="@string/minor2" />

    <Button
        android:id="@+id/Maj2_Button"
        android:layout_width="52dp"
        android:layout_height="80dp"
        android:layout_below="@+id/Progressbar"
        android:onClick="buttonClicked2"
        android:layout_marginTop="100dp" 
        android:layout_toRightOf="@+id/min2_Button"
        android:text="@string/major2" />

    <Button
        android:id="@+id/min3_Button"
        android:layout_width="52dp"
        android:layout_height="80dp"
        android:layout_below="@+id/Progressbar"
        android:onClick="buttonClicked2"
        android:layout_marginTop="100dp" 
        android:layout_toRightOf="@+id/Maj2_Button"
        android:text="@string/minor3" />

    <Button
        android:id="@+id/Maj3_Button"
        android:layout_width="52dp"
        android:layout_height="80dp"
        android:layout_below="@+id/Progressbar"
        android:onClick="buttonClicked2"
        android:layout_marginTop="100dp" 
        android:layout_toRightOf="@+id/min3_Button"
        android:text="@string/major3" />

    <Button
        android:id="@+id/P4_Button"
        android:layout_width="52dp"
        android:layout_height="80dp"
        android:layout_below="@+id/Progressbar"
        android:onClick="buttonClicked2"
        android:layout_marginTop="100dp" 
        android:layout_toRightOf="@+id/Maj3_Button"
        android:text="@string/perfect4" />



    <Button
        android:id="@+id/A4_Button"
        android:layout_width="52dp"
        android:layout_height="80dp"
        android:layout_below="@+id/Octave_Button"
        android:onClick="buttonClicked2"
        android:layout_marginTop="15dp"
        android:layout_marginLeft="5dp"
        android:text="@string/tritone" />

    <Button
        android:id="@+id/P5_Button"
        android:layout_width="52dp"
        android:layout_height="80dp"
        android:layout_below="@+id/min2_Button"
        android:onClick="buttonClicked2"
        android:layout_marginTop="15dp"
        android:layout_toRightOf="@+id/A4_Button"
        android:text="@string/perfect5" />

    <Button
        android:id="@+id/minor6_Button"
        android:layout_width="52dp"
        android:layout_height="80dp"
        android:layout_below="@+id/Maj2_Button"
        android:onClick="buttonClicked2"
        android:layout_marginTop="15dp"
        android:layout_toRightOf="@+id/P5_Button"
        android:text="@string/minor6" />

     <Button
        android:id="@+id/Major6_Button"
        android:layout_width="52dp"
        android:layout_height="80dp"
        android:layout_below="@+id/min3_Button"
        android:onClick="buttonClicked2"
        android:layout_marginTop="15dp"
        android:layout_toRightOf="@+id/minor6_Button"
        android:text="@string/major6" />

    <Button
        android:id="@+id/minor7_Button"
        android:layout_width="52dp"
        android:layout_height="80dp"
        android:layout_below="@+id/Maj3_Button"
        android:onClick="buttonClicked2"
        android:layout_marginTop="15dp"
        android:layout_toRightOf="@+id/Major6_Button"
        android:text="@string/minor7" />


    <Button
        android:id="@+id/Major7_Button"
        android:layout_width="52dp"
        android:layout_height="80dp"
        android:layout_below="@+id/P4_Button"
        android:onClick="buttonClicked2"
        android:layout_marginTop="15dp"
        android:layout_toRightOf="@+id/minor7_Button"
        android:text="@string/major7" />

回答by jlhonora

I think it's better if you pass the progress bar as an argument to the AsyncTask:

我认为最好将进度条作为参数传递给AsyncTask

final ProgressBar progressBar = (ProgressBar) findViewById(R.id.Progressbar);
progressBar.setProgress(0);

// Play Methods
final ImageButton Play = (ImageButton) findViewById(R.id.Play);
Play.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View view) {
        AsyncTaskBar task = new AsyncTaskBar();
        task.setProgressBar(progressBar);
        task.execute();
    }

And then on your AsyncTaskdeclare the setProgressBarmethod:

然后在你AsyncTask声明setProgressBar方法上:

public class ShowDialogAsyncTask extends AsyncTask<Void, Integer, Void> {

ProgressBar bar;

public void setProgressBar(ProgressBar bar) {
    this.bar = bar;
}

@Override
protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values);
    if (this.bar != null) {
        bar.setProgress(values[0]);
    }
}

You could do the same with the TextViewyou're trying to set.

你可以对TextView你试图设置的做同样的事情。

In any case, since you mentioned you're new at this you may want to take a look at the Broadcast/Receiver pattern. Here's how it goes:

无论如何,既然你提到你是新手,你可能想看看广播/接收器模式。这是它的过程:

  1. Start the async task without setting the progress bar or anything.
  2. Define a BroadcastReceiver, instantiate one in your activity and register/unregister it accordingly.
  3. Whenever there's a progress update on your async task just call sendBroadcast with the progress update as an intent extra. You may need to pass a context parameter when instantiating the AsyncTask.
  4. The onHandleIntent method of your app's broadcast receiver (the one you instantiated on step 2) will run on the UI thread, making all those UI updates safe.
  1. 在不设置进度条或任何东西的情况下启动异步任务。
  2. 定义一个BroadcastReceiver,在您的活动中实例化一个并相应地注册/取消注册。
  3. 每当您的异步任务有进度更新时,只需将进度更新作为额外意图调用 sendBroadcast。实例化 AsyncTask 时,您可能需要传递上下文参数。
  4. 您的应用程序的广播接收器(您在第 2 步中实例化的那个)的 onHandleIntent 方法将在 UI 线程上运行,从而确保所有这些 UI 更新都是安全的。

Sounds a bit overwhelming? It is at first, but here are the benefits:

听起来有点不知所措?一开始是这样,但这里有好处:

  1. It is much cleaner than passing UI objects to an AsyncTask.
  2. You will learn a powerful Android pattern that will come in handy in other endeavours.
  3. It will save you a lot of hassle (and exceptions) if you switch context or your app is low on memory.
  1. 它比将 UI 对象传递给 AsyncTask 干净得多。
  2. 您将学习一个强大的 Android 模式,它将在其他工作中派上用场。
  3. 如果您切换上下文或您的应用程序内存不足,它将为您节省很多麻烦(和例外)。

回答by Code-Apprentice

Intervals.getApp().progressBar.setProgress(values[0]);

There are two possibilities for the NullPointerExceptionin this line of code:

NullPointerException这行代码中有两种可能:

  1. getApp()returns null
  2. progressBaris null
  1. getApp()返回 null
  2. progressBarnull

In order to determine which is the cause, you need to split this into two separate lines:

为了确定哪个是原因,您需要将其分成两行:

Intervals intervals = Intervales.getApp();
intervals.progressBar.setProgress(values[0]);

Now set a breakpoint at the first line, step over it, and determine if intervalsis nullor not.

现在在第一行设置一个断点,跳过它,并确定是否intervalsnull

回答by Hyper Cube

progressBar is a local variable while you are referring to the same-named variable of a different class-object (in your case, the app object). you have probably mixed them up.

progressBar 是一个局部变量,而您指的是不同类对象(在您的情况下,应用程序对象)的同名变量。你可能把它们搞混了。