我有一个由一组方法调用的AsyncTask:
makeCall1();
makeCall2();
makeCall3();
makeCall4();
makeCall5();
每个问题都有一个“状态信息”,需要在运行时显示。因为我让它们像我一样运行,所以它们一起运行,“状态信息”做了一个大的改变。我想要的是让它逐步完成每个调用,只在第一个AsyncTask完成后才生成下一个调用。
我的异步完成如下:
public class JSONParser extends AsyncTask<String, String, JSONObject> {
InputStream is = null;
JSONObject json = null;
String outPut = "";
protected void onPreExecute(String f){
}
@Override
protected JSONObject doInBackground(String... params) {
// TODO Auto-generated method stub
...
publishProgress(params[3]);
...
return json;
}
protected void onProgressUpdate(String...values) {
statusMessage.setText(values[0]);
}
protected void onPostExecute(JSONObject result) {
}
}
一次拨打一个电话的最佳方法是什么?
-----编辑-----
要求的附加代码
我已经更改了下面的内容的名称并放置了“....”,其中代码片段在保存到数据库时并不真正相关:
public class SplashScreen extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash_screen);
statusMessage = (TextView) findViewById(R.id.statusMessage);
}
protected void onResume(){
super.onStart();
if(isNetworkAvailable()){
statusMessage.setText("Connection Found");
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
final String appUpdateDate = null;
getAPI1(appUpdateDate);
getAPI2(appUpdateDate);
getAPI3(appUpdateDate);
getAPI4(appUpdateDate);
getAPI5(appUpdateDate);
getAPI6(appUpdateDate);
endSplash();
}
}, SPLASH_TIME_OUT);
}
else {
statusMessage.setText("No Connection Found");
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
endSplash();
}
}, SPLASH_TIME_OUT);
}
}
public void endSplash(){
....
goes to main activity after timeout
....
}
private boolean isNetworkAvailable() {
....
checks for internet connection
....
}
//this is an example of getAPI1. There are 5 more but each do a different database and api call. The AsyncTask is what does the api call and parses the json it returns.
public void getAPI1(String appUpdateDate){
String URL = "http://API_URL";
String requestType = "X";
String getType = "Y";
URL = URL+requestType+"/"+getType;
SQLiteDatabase database = APIDB.getWritableDatabase();
try {
JSONObject output = new JSONParser().execute(new String[] {URL,consumerKey,sharedSecret,"Updating X"}).get();
JSONArray jsonx = output.getJSONArray("Data");
....
runs through jsonX and saves data to database
....
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public class JSONParser extends AsyncTask<String, String, JSONObject> {
InputStream is = null;
JSONObject json = null;
String outPut = "";
protected void onPreExecute(String f){
}
@Override
protected JSONObject doInBackground(String... params) {
// TODO Auto-generated method stub
publishProgress(params[3]);
String url = params[0];
String ck = params[1];
String ss = params[2];
Log.d("url",url);
Log.d("ck",ck);
Log.d("ck",ss);
List<NameValuePair> values = new ArrayList<NameValuePair>();
values.add(new BasicNameValuePair("ConsumerKey", ck));
values.add(new BasicNameValuePair("SharedSecret", ss));
try {
....
get the json from the api
....
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
....
parse the json to be returned
....
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
try {
json = new JSONObject(outPut);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return json;
}
protected void onProgressUpdate(String...values) {
statusMessage.setText(values[0]);
}
protected void onPostExecute(JSONObject result) {
}
}
}
答案 0 :(得分:2)
从API级别11 / Honeycomb开始,默认的asynctask执行程序为SERIAL_EXECUTOR
,因此单个asynctasks已经串行执行,除非您明确指定例如THREAD_POOL_EXECUTOR
。因此,如果您的最小和目标SDK版本都是11或更高,只需execute()
您的asynctasks,它们将在执行程序可用时立即运行。
要处理状态消息等UI更新,请使用onPreExecute()
,onProgressUpdate()
和/或onPostExecute()
。如果需要将其他参数传递给异步任务,可以在构造函数args中赋予它们并存储在成员变量中。
答案 1 :(得分:1)
public class JSONParser extends AsyncTask<String, String, JSONObject> {
OnFinished onFinished;
JsonParser(OnFinished onFinishedWithTask) {
this.onFinished = onFinishedWithTask;
}
InputStream is = null;
JSONObject json = null;
String outPut = "";
protected void onPreExecute(String f) {
}
@Override
protected JSONObject doInBackground(String... params) {
// TODO Auto-generated method stub
...
publishProgress(params[3]);
...
return json;
}
protected void onProgressUpdate(String... values) {
statusMessage.setText(values[0]);
}
protected void onPostExecute(JSONObject result) {
this.onFinished.onFinishedWithTask();
}
}
public interface OnFinished {
public void onFinishedWithTask();
}
这样的事可能适合你。
然后调用第一个,当它完成后调用第二个,依此类推......如果你需要在'onprogressupdate'中更新ui,只需在界面中创建另一个方法并调用它。
下面是一个更大的例子,让您了解一个人如何做到这一点:
public class DownloadWebPage extends AsyncTask<String, Integer, StringBuilder> {
private OnProgressUpdate updateInter;
private String url;
public DownloadWebPage() {
super();
}
public DownloadWebPage(OnProgressUpdate updateInter) {
this.updateInter = updateInter;
}
public DownloadWebPage(OnProgressUpdate updateInter, String url) {
this(updateInter);
this.url = url;
}
@Override
protected StringBuilder doInBackground(String... url) {
System.out.println("start downloading");
try {
System.out.println("url 0 =" + url[0]);
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(url[0]);
HttpResponse response = client.execute(request);
BufferedReader rd = new BufferedReader(new InputStreamReader(
response.getEntity().getContent()));
long content = response.getEntity().getContentLength();
String line = "";
StringBuilder htmlBuilder = new StringBuilder();
long bytesRead = 0;
while ((line = rd.readLine()) != null) {
htmlBuilder.append(line);
bytesRead = bytesRead + line.getBytes().length + 2;
publishProgress(new Integer[] { (int) (((double) bytesRead / (double) content) * 100) });
}
System.out.println("end downloading");
return htmlBuilder;
} catch (IOException e) {
System.out.println(e.toString());
return null;
}
}
@Override
protected void onProgressUpdate(Integer... values) {
if (values[0].equals(Math.abs(values[0]))) {
updateInter.onUpdate(values[0]);
} else if (!values[0].equals(Math.abs(values[0]))) {
updateInter.onUpdateFailure();
}
}
@Override
protected void onPostExecute(StringBuilder result) {
if (result == null) {
updateInter.onFailure();
} else if (result != null) {
updateInter.onSuccess(result);
}
}
public void setOnProgressUpdate(OnProgressUpdate updateInter) {
this.updateInter = updateInter;
}
public void downloadHtml() {
if (url == null) {
updateInter.onFailure();
return;
}
System.out.println("STATUS=" + getStatus());
if (getStatus().equals(AsyncTask.Status.FINISHED)) {
DownloadWebPage iseDownloader = new DownloadWebPage();
iseDownloader.setOnProgressUpdate(updateInter);
iseDownloader.execute(new String[] { url });
} else if (getStatus().equals(AsyncTask.Status.RUNNING)) {
} else {
execute(new String[] { url });
}
}
public void downloadHtml(String urlToDownload) {
this.url = urlToDownload;
downloadHtml();
}
}
继承人界面:
public interface OnProgressUpdate {
public void onUpdate(Integer percentProgress);
public void onUpdateFailure();
public void onSuccess(StringBuilder result);
public void onFailure();
}
Heres用法:
public final class OnProgressUpdater implements OnProgressUpdate {
private final FortschoolsFragment fortSchoolsFragment;
private final SchoolActivity a;
public OnProgressUpdater(SherlockFragment fragment, Activity a) {
this.fortSchoolsFragment = (FortschoolsFragment) fragment;
this.a = (SchoolActivity) a;
this.a.startRefreshing();
this.a.disableSpinner();
}
@Override
public void onUpdate(Integer percentProgress) {
// TODO Auto-generated method stub
}
@Override
public void onUpdateFailure() {
// TODO Auto-generated method stub
}
@Override
public void onSuccess(StringBuilder result) {
final Document doc = Jsoup.parse(result.toString());
final Site site = new FortSchoolSite(doc);
dataList = site.getNews();
if (JavaUtility.isNull(fortSchoolsFragment.getSherlockActivity())) {
return;
}
mListViewAdapter = new DataAdapter(fortSchoolsFragment
.getSherlockActivity().getApplicationContext(), dataList);
mListView.setAdapter(mListViewAdapter);
this.a.stopRefreshing();
this.a.enableSpinner();
}
@Override
public void onFailure() {
this.a.stopRefreshing();
this.a.enableSpinner();
Toast.makeText(a.getApplicationContext(), "Something Went Wrong",
Toast.LENGTH_LONG).show();
}
}
现在使用以下方法调用OnProgressUpdater:
DownloadWebPage page = new DownloadWebPage(new OnProgressUpdater(this,
getSherlockActivity()), this.mSchool.getSchoolUrl());
page.downloadHtml();
我们正在制作自己的 OnClickListener 。
回到你的例子。当调用接口的onFinishedWithTask();
方法时,我们只会启动另一个asynchtask。
另一种选择是跳过* AsynchTask * 并使用传统的java线程。你将创建一个实现Runnable的私有内部类,然后在run()中完成你的工作;方法并通过runOnUiThread方法更新ui。
跳过asynchtask的示例:
protected class SdfaOverviewThread implements Runnable {
private static final String SOMEURL = "SOMEURLGOESHERE";
@Override
public void run() {
//not proper but does illustrate point
Document doc = Jsoup.connect(SOMEURL).get();
final Document runOnUiDoc = doc;
runOnUiThread(new Runnable() {
@Override
public void run() {
/* Html parsing is just an example showing what one could do.
* Do not worry about fragment details either they are just illustrating a point*/
SdfaOverviewFragment sdfaOverviewFrag = ((SdfaOverviewFragment) getSupportFragmentManager()
.findFragmentById(R.id.FrameLayout1));
String theme = runOnUiDoc.select("head").select("style")
.get(1).toString();
String upcomingEvents = runOnUiDoc.select(
"div#sw-innerWrap2").toString();
String news = runOnUiDoc.select("div#sw-newsContainer")
.toString();
String quickLinks = runOnUiDoc.select("div.sw-column")
.toString();
String html = theme + upcomingEvents; //+ news + quickLinks;
sdfaOverviewFrag.getWebView().loadDataWithBaseURL(
SOMEURL, html, "text/html", "UTF-8",
SOMEURL);
}
});
Log.d(TAG, "Finished Running Thread");
}
}
现在我们执行:
Thread thread = new Thread(new SdfaOverviewThread());
thread.start();
跳过Asynchtask也可以适用于你的情况。
回顾一下,你可以:
使用您认为创建最易维护代码的方法。
修改强> 我只能给你一些例子;考虑发布更多代码。
public class JSONParser extends AsyncTask<String, String, JSONObject> {
private OnFinished onFinished;
public JSONParser(OnFinished onFinished) {
this.onFinished = onFinished;
}
@Override
protected JSONObject doInBackground(String... arg0) {
JSONObject object = new JSONObject();
// get data from arg0
return object;
}
@Override
protected void onProgressUpdate(String... values) {
onFinished.onProgressUpdate(Integer.parseInt(values[0]));
}
@Override
protected void onPostExecute(JSONObject result) {
onFinished.onFinishedWithTask(result);
}
}
public interface OnFinished {
public void onProgressUpdate(Integer percentProgress);
public void onFinishedWithTask(JSONObject object);
}
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Stack<String> data = new Stack<String>();
data.push("jsonData");
data.push("jsonData");
data.push("jsonData");
data.push("jsonData");
data.push("jsonData");
JSONParser parser = new JSONParser(new Parser(data));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class Parser implements OnFinished {
private Stack<String> stack;
public Parser(Stack<String> stack) {
this.stack = stack;
}
@Override
public void onProgressUpdate(Integer percentProgress) {
// update ui from percent progress;
}
@Override
public void onFinishedWithTask(JSONObject object) {
// if their are no more objects left we will do nothing or else we
// will create a new Asynchtask
if (stack.isEmpty()) {
return;
}
new JSONParser(this).execute(stack.pop());
}
}
}
基本思想是,当调用onFinishedTask(JsonObject obj)时,你将从JsonObject obj更新用户界面,然后启动一个新的asynchtask,直到你的数据用完为止。
做类似的事情(你只实例化一次):
public class JSONParser extends AsyncTask<String, String, JSONObject> {
InputStream is = null;
JSONObject json = null;
String outPut = "";
private int api;
public JSONParser(int api) {
this.api= api;
}
protected void onPreExecute(String f){
}
@Override
protected JSONObject doInBackground(String... params) {
String appUpdateDate = params[0];
String url = null;
String ck = null;
String ss = null;
String updating = null;
switch(api){
case
11:
String URL = "http://API_URL";
String requestType = "X";
String getType = "Y";
URL = URL+requestType+"/"+getType;
SQLiteDatabase database = APIDB.getWritableDatabase();
/*
* Write to vars url ck ss updating
*/
break;
}
Log.d("url",url);
Log.d("ck",ck);
Log.d("ck",ss);
List<NameValuePair> values = new ArrayList<NameValuePair>();
values.add(new BasicNameValuePair("ConsumerKey", ck));
values.add(new BasicNameValuePair("SharedSecret", ss));
try {
....
get the json from the api
....
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
....
parse the json to be returned
....
} catch (Exception e) {
Log.e("Buffer Error", "Error converting result " + e.toString());
}
try {
json = new JSONObject(outPut);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
// return JSON String
return json;
}
protected void onProgressUpdate(String...values) {
statusMessage.setText(values[0]);
}
protected void onPostExecute(JSONObject result) {
/*
* Do something to update ui with result
*/
api++;
if(api > 6){
return;
}
new JSONParser(api).execute("insert data here");
}
答案 2 :(得分:0)
因为这些方法不接受任何变量,为什么不只是在每个函数中都有一个回调函数,并且对下一个函数进行超时并捎带它们?