我使用AsyncTask执行一个很长的过程。
我不想将我的长进程代码直接放在doInBackground中。相反,我的长进程代码位于另一个类中,我在doInBackground中调用。
我希望能够从longProcess函数中调用publishProgress。 在C ++中,我将一个sendProgress的回调指针传递给我的longProcess函数。
我如何在java中做到这一点?
编辑:
我的长程序代码:
public class MyLongProcessClass
{
public static void mylongProcess(File filetoRead)
{
// some code...
// here I would like to call publishProgress
// some code...
}
}
我的AsyncTask代码:
private class ReadFileTask extends AsyncTask<File, Void, Boolean>
{
ProgressDialog taskProgress;
@Override
protected Boolean doInBackground(File... configFile)
{
MyLongProcessClass.mylongProcess(configFile[0]);
return true;
}
}
编辑#2。编辑#2
长处理方法也可以是非静态的,并且如下所示:
MyLongProcessClass fileReader = new MyLongProcessClass();
fileReader.mylongProcess(configFile[0]);
但这不会改变我的问题。
答案 0 :(得分:33)
困难在于publishProgress
为protected final
所以即使您将this
传递到static
方法调用中,您仍然无法直接调用publishProgress
。
我自己没试过,但是怎么样:
public class LongOperation extends AsyncTask<String, Integer, String> {
...
@Override
protected String doInBackground(String... params) {
SomeClass.doStuff(this);
return null;
}
...
public void doProgress(int value){
publishProgress(value);
}
}
...
public class SomeClass {
public static void doStuff(LongOperation task){
// do stuff
task.doProgress(1);
// more stuff etc
}
}
如果有效,请告诉我!请注意,从doProgress
调用的方法以外的任何地方调用doInBackground
几乎肯定会导致错误。
对我来说感觉很脏,其他人有更好的方法吗?
答案 1 :(得分:5)
解决方案可能是在AsyncTask中放置一个简单的public
类(确保您定义的任务也是public
),该类具有调用public
的{{1}}方法。通过该课程应该可以从任何其他包或类中获得。
publishProgress(val)
然后在另一个班级:
public abstract class MyClass {
public MyClass() {
// code...
}
// more code from your class...
public class Task extends AsyncTask<String, Integer, Integer> {
private Progress progress;
protected Task() {
this.progress = new Progress(this);
}
// ...
@Override
protected Integer doInBackground(String... params) {
// ...
SomeClass.doStuff(progress);
// ...
}
// ...
@Override
protected void onProgressUpdate(Integer... progress) {
// your code to update progress
}
public class Progress {
private Task task;
public Progress(Task task) {
this.task = task;
}
public void publish(int val) {
task.publishProgress(val);
}
}
}
}
这对我有用。
答案 2 :(得分:2)
将longProcess()
功能拆分为较小的功能。
示例代码:
@Override
protected Boolean doInBackground(Void... params) {
YourClass.yourStaticMethodOne();
publishProgress(1);
YourClass.yourStaticMethodTwo();
publishProgress(2);
YourClass.yourStaticMethodThree();
publishProgress(3);
// And so on...
return true;
}
答案 3 :(得分:1)
如果有效,请告诉我!请注意,从doInBackground调用的方法以外的任何地方调用doProgress几乎肯定会导致错误。
是的,它有效。我扩展它,以便您不需要将AsyncTask作为参数传递给您的方法。如果(像我一样)在决定实际上你需要发布一些进度之前已经编写了所有方法,或者在我的情况下,从AsyncTask更新UI时,这个特别有用:
public abstract class ModifiedAsyncTask<A,B,C> extends AsyncTask<A,B,C>{
private static final HashMap<Thread,ModifiedAsyncTask<?,?,?>> threads
= new HashMap<Thread,ModifiedAsyncTask<?,?,?>>();
@Override
protected C doInBackground(A... params) {
threads.put(Thread.currentThread(), this);
return null;
}
public static <T> void publishProgressCustom(T... t) throws ClassCastException{
ModifiedAsyncTask<?, T, ?> task = null;
try{
task = (ModifiedAsyncTask<?, T, ?>) threads.get(Thread.currentThread());
}catch(ClassCastException e){
throw e;
}
if(task!=null)
task.publishProgress(t);
}
}
public class testThreadsActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void Button1Clicked(View v){
MyThread mthread = new MyThread();
mthread.execute((Void[])null);
}
private class MyThread extends ModifiedAsyncTask<Void, Long, Void>{
@Override
protected Void doInBackground(Void... params) {
super.doInBackground(params);
while(true){
myMethod(System.currentTimeMillis());
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
return null;
}
}
}
protected void onProgressUpdate(Long... progress) {
//Update UI
((TextView) findViewById(R.id.textView2)).setText("The Time is:" + progress[0]);
}
}
private void myMethod(long l){
// do something
// request UI update
ModifiedAsyncTask.publishProgressCustom(new Long[]{l});
}
}
对我来说感觉很脏,其他人有更好的方法吗?
我的方式可能更糟。我正在为doProgress调用一个静态方法(我称之为publishProgressCustom)。它可以从任何地方调用而不会产生错误(好像该线程在hashMap中没有相应的AsyncTask,它不会调用publishProgress)。缺点是你必须在线程启动后自己添加Thread-AsyncTask映射。 (你不能轻易地覆盖AsyncTask.execute(),因为这是最终的)。我在这里通过覆盖超类中的doInBackground()来完成它,所以扩展它的任何人都必须将super.doInBackground()作为它们自己的doInBackground()中的第一行。
我不太了解Threads和AsyncTask,以便在Thread和/或AsyncTask结束后知道HashMap引用会发生什么。我怀疑发生了不好的事情,所以我不建议任何人尝试我的解决方案作为他们自己的一部分,除非他们知道更好
答案 4 :(得分:0)
当你说“我的长流程代码位于我在doInBackground中调用的另一个类”时,你的意思是“位于另一个方法中,我是在doInBackground中调用“?
如果是这样,您可以将该方法设置为AsynTask类的私有方法。然后,您可以在需要时在方法内调用publishProgress。