从doInBackground中的函数内部发布进程?

我使用一个AsyncTask执行一个漫长的过程。

我不想将我的长处理代码直接放在doInBackground中。 相反,我的长程序代码位于另一个类中,我在doInBackground中调用。

我想能够从longProcess函数中调用publishProgress。 在C ++中,我会传递一个callback指针到publishProgress到我的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长的过程方法也可以是非静态的,如下所示:

 MyLongProcessClass fileReader = new MyLongProcessClass(); fileReader.mylongProcess(configFile[0]); 

但是这并不能改变我的问题。

Solutions Collecting From Web of "从doInBackground中的函数内部发布进程?"

难点在于publishProgressprotected 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 } } 

如果这个工作,请让我知道! 请注意,从doInBackground调用的方法以外的地方调用doInBackground几乎肯定会导致错误。

对我感觉很肮脏,其他人有更好的办法吗?

一个解决scheme可能是在AsyncTask中放置一个简单的public类(确保您定义的任务也是public ),它具有一个调用publishProgress(val)public方法。 通过该课程应该可以从任何其他包装或课程。

 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); } } } } 

然后在其他class级:

 public class SomeClass { public static void doStuff(Progress progress){ // do stuff progress.publish(20); // more stuff etc } } 

这对我有效。

longProcess()函数分解成更小的函数。

示例代码:

 @Override protected Boolean doInBackground(Void... params) { YourClass.yourStaticMethodOne(); publishProgress(1); YourClass.yourStaticMethodTwo(); publishProgress(2); YourClass.yourStaticMethodThree(); publishProgress(3); // And so on... return true; } 

如果这个工作,请让我知道! 请注意,从doInBackground调用的方法以外的地方调用doProgress几乎肯定会导致错误。

是的,它的工作。 我扩展了它,以便您不需要将AsyncTask作为parameter passing给您的方法。 如果(像我一样)在决定实际上需要发布一些进度之前已经编写了所有的方法,或者在我的情况下,从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()的第一行。

一旦Thread和/或AsyncTask结束,我不太了解Threads和AsyncTask知道HashMap引用会发生什么。 我怀疑发生了不好的事情,所以我不会build议任何人尝试我的解决scheme作为自己的一部分,除非他们知道更好

当你说“ 我的长程序代码位于我在doInBackground中调用的另一个类中 ”时,你的意思是“ 位于我在doInBackground中调用的另一个方法 ”中吗?

如果是这样,你可以使该方法成为AsynTask类的私有方法。 然后,只要需要,就可以在方法内部调用publishProgress。