0

I'm trying to run many AsyncTasks to do loadData() on the same WebView. For example, I have 3 threads with 3 contents: "One", "Two", "Three" and a WebView with content "abc". (like the code below)

After 3 tasks finished, I want the WebView has content: "abcOneTwoThree". The idea of this code is that three threads will append its content to WebView at anytime, so the result could be "abcTwoOneThree" or "abcTwoThreeOne", etc ...

I read many concurrency articles but still don't understand how to implement this. This is my code. It just prints "abcThree".

public class UsingSameWebViewActivity extends Activity implements OnClickListener {
    private Button button1;
    private WebView webView;
    private String result;

    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        button1 = (Button)findViewById(R.id.button1);
        button1.setOnClickListener(this);
        webView = (WebView)findViewById(R.id.webView1);
        result = "abc";
    }

    @Override
    public void onClick(final View v) {
        final String[] contents = {"One", "Two", "Three"};
        for(int i = 0; i < 3; ++i) {
            final FooTask task = new FooTask(webView, result);
            task.execute(contents[i]);
        }
    }

    private class FooTask extends AsyncTask<String, Void, String> {
        private final WebView resultView;
        private String result;

        // This is what I try to make it work right.
        private synchronized String getResult() {
            return result;
        }

        public FooTask(final WebView resultView, final String result) {
            this.resultView = resultView;
            this.result = result;
        }

        @Override
        protected String doInBackground(final String... params) {
        // Do a long time work randomly then returns a string.
            return params[0];
        }

        @Override
        protected void onPostExecute(final String content) {
            result = getResult() + content;
            resultView.loadData(result, "text/html", "utf-8");
        }
    }
}
emeraldhieu
  • 9,380
  • 19
  • 81
  • 139

3 Answers3

1

There is nothing much to do here.. just add this line task.execute(contents[i]); in postExecute() of AsynTask and make contents[i] as a class variable.. task.execute(contents[i]); call this twice since you want it to do "one" and "two"

ngesh
  • 13,398
  • 4
  • 44
  • 60
  • No, I want each task appends its content to result variable then load it on WebView immediately. i.e. Task A appends 'One' to result, Task B appends 'Two' to result, ... the order is not important. If I misunderstood your answer, please add some code. – emeraldhieu Aug 01 '11 at 10:45
  • Thats what i'm trying to say.. You can call asyncTask inside postExecute multiple times.. and it probably will serve your purpose.. – ngesh Aug 01 '11 at 10:58
1

Remove the private String result; line from the Async Task class.

Arnab Chakraborty
  • 7,442
  • 9
  • 46
  • 69
1

In onPostExecute() you want to "return" your result somewhere. This is to say FooTask needs a place to put its result. A likely candidate would be some sort of method FooTask can call on its caller to place the result. If you do this note that the method must be synchronized, otherwise some of the returns may be lost.

Alternately you could give FooTask a Handler that it can send a Message to with the result. In this case, you will not need to synchronize anything since all the Messages will be sent to the main/UI thread which will process them serially.

cyngus
  • 1,763
  • 13
  • 14