如何在Android中以编程方式在AsyncTask中隐藏ProgressBar?

时间:2019-03-11 18:35:22

标签: android android-asynctask android-progressbar

我有以下静态AsyncTask类:

public static class MyAsyncTask extends AsyncTask<String, Void, String> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressBar.setVisibility(View.VISIBLE);
    }

    @Override
    protected String doInBackground(String... params) {
        //Do heavy stuff
    }

    @Override
    protected void onPostExecute(String string) {
        super.onPostExecute(string);
        progressBar.setVisibility(View.GONE);
    }
}

我想显示/隐藏progressBar,就像您在这两种方法中看到的那样。问题是我必须将progressBar设为静态。这样做,我得到:

  

请勿将Android上下文类放在静态字段中;这是内存泄漏(还会中断即时运行)

如果我删除了MyAsyncTask类前面的静态变量,则会得到:

  

此AsyncTask类应该是静态的,否则可能会发生泄漏(MainActivity.MyAsyncTask)

如何解决这个问题?

编辑:

private void checkUser() {
    uidRef.get().addOnCompleteListener(task -> {
        if (task.isSuccessful()) {
            DocumentSnapshot document = task.getResult();
            User user = document.toObject(User.class);
            if (user == null) {
                MyAsyncTask myAsyncTask = new MyAsyncTask();
                myAsyncTask.execute(url);
            }
        }
    });
}

2 个答案:

答案 0 :(得分:1)

我之前在异步任务中遇到了这个“静态”问题,有一种非常不错的方法可以将异步任务的输出恢复为活动状态。简而言之

String output = myAsyncTask.execute(url).get();

您将获得输出,最终代码是。

progressBar.setVisibility(View.VISIBLE);                                  
String output = myAsyncTask.execute(url).get();
progressBar.setVisibility(View.GONE);

在获得输出之前,将不执行下一行。我正在添加示例代码以进行进一步的演示。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Button exe = findViewById(R.id.async);
    exe.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            try {
                updateAsyncTask up = new updateAsyncTask();

                long l = up.execute().get();
                System.out.println("inside main "+l);                    
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });


}

 private static class updateAsyncTask extends AsyncTask<Void, Void, Long> {

    @Override
    protected Long doInBackground(Void... voids) {

        long l = 0;
        for(int i=0;i<2000;i++)
        {
            l = l+i;
            System.out.println(l);              

        }
        return l;
    }

    }

答案 1 :(得分:0)

对于使用asyncTask作为静态子类并解决它,我遇到了同样的问题,我使用了方法反射。这可能有点棘手,但对我有用:

public class MainClass{
 @keep
 public void AfterLoad(String value) {

  }
 public void callAsync() {
   Class[] parameterTypes = new Class[1];
    parameterTypes[0] = String.class;
    try {
        Method method1 = MainClass.class.getMethod("AfterLoad", 
  parameterTypes);
        MyAsyncTask task = new MyAsyncTask(this, method1);
        task.execute(link);
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }
  }

public static class MyAsyncTask extends AsyncTask<String, String, Void> {
    private final Method mAfterLoad;
    private final Object mOwner;

    public MyAsyncTask(Object owner, Method afterLoad) {
        this.mAfterLoad = afterLoad;
        this.mOwner = owner;
    }  
   @Override
    protected Void doInBackground(String... requests) {
     // do what you want
    }

    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        if (mAfterLoad != null) {
            try {
                Object[] parameters = new Object[1];
                parameters[0] = values[0];
                mAfterLoad.invoke(mOwner, parameters);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
 }

这样可以克服内存泄漏的问题,但是请注意,调用该方法时,它的名称将作为字符串传递,您应该添加@keep注释以将其保存在保护措施的优化和重构中。