如何在 Android 中以编程方式隐藏 AsyncTask 中的 ProgressBar?
How to hide a ProgressBar in AsyncTask programmatically in Android?
我有以下静态 AsyncTask
class:
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);
}
}
我想 show/hide progressBar
正如您在这两种方法中看到的那样。问题是我必须使 progressBar
静态化。这样做,我得到:
Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)
如果我删除留在 MyAsyncTask
class 前面的静电,我得到:
This AsyncTask class should be static or leaks might occur (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);
}
}
});
}
我之前在异步任务中遇到过这个 "static" 问题,有一种非常好的方法可以将异步任务的输出返回到 activity 。简单地说
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;
}
}
我在将 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 注释以将其从 pro-guard 优化中保存并且重构。
我有以下静态 AsyncTask
class:
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);
}
}
我想 show/hide progressBar
正如您在这两种方法中看到的那样。问题是我必须使 progressBar
静态化。这样做,我得到:
Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)
如果我删除留在 MyAsyncTask
class 前面的静电,我得到:
This AsyncTask class should be static or leaks might occur (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);
}
}
});
}
我之前在异步任务中遇到过这个 "static" 问题,有一种非常好的方法可以将异步任务的输出返回到 activity 。简单地说
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;
}
}
我在将 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 注释以将其从 pro-guard 优化中保存并且重构。