问题
Here is my sample code.
public class test extends Activity {
private TextView tv;
public class Blap extends AsyncTask<String,String,Boolean>{
private test parent;
@Override
protected Boolean doInBackground(String... options) {
this.auth(options[0],options[1]);
parent.aresponse(res);
return true;
}
public Blap(test a){
this.parent = a;
}
public auth(String login, String password){
//process auth
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
//work...
}
public void buttonclick(View v){
tv = new TextView(this);
new Blap(this).execute(editText1.getText().toString(),editText2.getText().toString());
setContentView(tv);
}
public void aresponse(String rs){
tv.setText(rs);
}
}
But when aresponse is called, I got an exception: only the original thread that created a view hierarchy can touch its views. How do I correctly wait for async operation complete and continue processing needed operations?
回答1:
AsyncTask
offers you two posibilites to update the UI :
If you want to update the UI in parallel with the task executed in doInBackground()
(e.g. to update a ProgressBar
), you'll have to call publishProgress()
inside the doInBackground()
method. Then you have to update the UI in the onProgressUpdate()
method.
If you want to update the UI when the task is done, you have to do it in the onPostExecute()
method.
/** This method runs on another thread than the UI thread */
@Override
protected String doInBackground(String... _params) {
for (int progressValue = 0; progressValue < 100; progressValue++) {
publishProgress(progressValue);
}
}
/** This method runs on the UI thread */
@Override
protected void onProgressUpdate(Integer... progressValue) {
// TODO Update your ProgressBar here
}
/**
* Called after doInBackground() method
* This method runs on the UI thread
*/
@Override
protected void onPostExecute(Boolean _result) {
// TODO Update the UI thread with the final result
}
In your case, you should use an AsyncTask<String, String, String>
because you need doInBackground()
to return a String. Then you just have to treat the result in onPostExecute()
public class test extends Activity {
private TextView tv;
@Override
public void onCreate(Bundle savedInstanceState) {
//work...
}
public void buttonclick(View v){
tv = new TextView(this);
new Blap().execute(editText1.getText().toString(), editText2.getText().toString());
setContentView(tv);
}
public class Blap extends AsyncTask<String, String, String> {
private test parent;
@Override
protected String doInBackground(String... options) {
this.auth(options[0], options[1]);
String result = "my result";
return result;
}
public auth(String login, String password){
//process auth
}
@Override
protected void onPostExecute(String _result) {
tv.setText(_result);
}
}
}
回答2:
Simply change your method aresponse
as below:
public void aresponse(String rs){
runOnUiThread(new Runnable() {
@Override
public void run() {
tv.setText(rs);
}
});
}
In this way when ever and from where ever you call this method, it will update your TextView on UI thread.
Moreover, you may also consider to call this method from AsyncTask's onPostExecute method which will run it without any problem, but then its your choice :)
回答3:
AsyncTask
has some methods which are automatically called on the UI thread. Override onPostExecute()
and call aresponse()
from there. More information is here: http://developer.android.com/reference/android/os/AsyncTask.html
来源:https://stackoverflow.com/questions/10316335/how-access-parent-class-view-from-callback-function-in-asynctask