我试图在SO上引用类似的问题,但没有得到任何帮助。
在我的Android应用程序中,我计划实现用户访问过的最近引用,即类似于最近访问过的网页。
以下是我正在遵循的步骤:
1。)每当用户打开任何公司视图时,从数据库中获取公司符号
2.)然后将当前符号与dateTime一起存储在数据库中。
3.。)对于从数据库中提取的所有符号,获取他们的current value
和%Change
并显示公司名称,当前值和%更改在列表中。
问题出现在ASyncTask
类中,postExecute
方法不允许其返回类型为void
以外的其他类型。
我做错了吗?
任何帮助都可以节省生命!
String[] rsym,rcmp,rchg;
rdbM = new RecentDBManager(CompanyView.this);
try {
Calendar date1 = Calendar.getInstance();
SimpleDateFormat dateformatter = new SimpleDateFormat(
"dd/MM/yyyy HH:mm:ss");
String currentdate = dateformatter.format(date1.getTime());
rdbM.openDB();
//STEP 1
rsym = rdbM.getRecent_sym();
//STEP 2
rdbM.setData(currentsymbol, currentdate);
rdbM.closeDB();
} catch (Exception e) {
throw new Error(" *** ERROR in DB Access *** "+ e.toString());
}
//STEP 3
for(int i=0;i<rsym.length;i++)
{
DownloadRecentQuote quotetask = new DownloadRecentQuote();
recentquotetask
.execute(new String[] { "http://abc.com/stockquote.aspx?id="
+ rsym[i] });
//CURRENT VALUE and %CHANGE which should be returned from ASyncTask class
rcmp[i]=valuearr[0];
rchg[i]=valuearr[1];
}
list1 = new ArrayList<HashMap<String, String>>();
HashMap<String, String> addList1;
for (int i = 0; i < limit; i++)
{
addList1 = new HashMap<String, String>();
addList1.put(RecentSym_COLUMN, rsym[i]);
addList1.put(RecentCMP_COLUMN, rcmp[i]);
addList1.put(RecentChg_COLUMN, rchg[i]);
list1.add(addList1);
RecentAdapter adapter1 = new RecentAdapter(
CompanyView.this, CompanyView.this, list1);
listrecent.setAdapter(adapter1);
}
private class DownloadRecentQuote extends AsyncTask<String, Void, String> {
/* Fetching data for RecentQuote information */
@Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(
new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}
@Override
protected void onPostExecute(String result) {
arr1 = result.split("@");
if (arr1[0].length() != 0) {
if (arr1[0].equals("1")) {
arr = arr1[1].split(";");
//RETURN 2 STRINGS
String valuearr[];
valuearr[0] = arr[3];
valuearr[1] = arr[6].concat("%");
//return valuearr;
}
}
}
答案 0 :(得分:8)
postExecute()无法返回值,因为它返回的是谁或者什么?您调用AsyncTask的原始方法已经消失,因为您的AsyncTask正在后台运行。当AsyncTask.execute()返回它仍在后台运行时,它是异步的,因此postExecute()不能返回值,因为没有任何东西可以返回它。
相反,您的AsyncTask需要一个引用回您的Activity或其他一些对象,以便它可以将您的值发回给它。在您的代码中,调用execute()之后的行不能存在,因为您的任务尚未完成。相反,您应该创建一个名为updateSymbol(currentPrice,percentChange)的方法,在那里移动execute()下面的所有代码,并在AsyncTask中传递对Activity的引用。然后从onPostExecute()方法调用updateSymbol(currentPrice,percentChange)。
但是,如果你有一个对一个Activity的引用,你可以在doInBackground()运行时将其销毁,并且当postExecute()运行时,它应该只删除结果或不尝试更新UI。例如,用户旋转他们的电话导致活动被销毁。我发现最好在活动中保存对AsyncTask的引用,这样如果活动被销毁,它可以取消()它。您可以调用AsyncTask.cancel()然后检查您的任务是否被取消,如:
public void postExecute( String result ) {
if( !isCanceled() ) {
// do your updating here
activity.setSymbol( result );
}
}
为所有活动创建基类非常容易,因此您可以轻松跟踪正在运行的AsyncTasks:
public class BaseActivity extends Activity {
List<AsyncTask> runningTasks;
public void onStop() {
for( AsyncTask task : runningTasks ) {
task.cancel(true);
}
}
public AsyncTask start( AsyncTask task ) {
runningTasks.add( task );
return task;
}
public void done( AsyncTask task ) {
runningTasks.remove( task );
}
}
一些快速指示。你不需要执行(new String [] {“blah”+ blah})。 Java中的Varargs允许您这样做。执行(“blah”+ blah)。你也正在捕捉异常并继续而不是真正处理它们。当一些事情发生真正发生因为你的应用程序捕获它们时会很难,并且就像没有发生任何事情一样继续。如果出现错误,您可能希望向用户提供一些反馈并停止尝试执行该过程。停止,向用户显示错误,让他们做下一件事。将catch块移动到方法的底部。
答案 1 :(得分:3)
本质上,在执行AsyncTask的doInBackground()并返回执行结果之后,AsyncTask.onPostExecute()是您要执行的任何操作。这应被视为最佳做法。
当从UI线程调用AsyncTask()。execute()时(注意必须从UI线程调用此方法),Android框架创建一个工作线程并开始运行您在AsyncTask.doInBackground()中编写的任何内容在这个工作线程上。此时(在调用新的AsyncTask()。execute()之后),UI线程继续在新的AsyncTask()。execute()之后执行代码。所以现在在运行时,你有两个线程(UI和工作线程)同时运行。
但AsyncTask执行结果何时何地从工作线程返回到UI线程?
工作线程(doInBackground())完成并返回到UI线程的点是AysncTask.onPostExecute()。一旦AsyncTask完成,该方法就保证由UI线程上的框架调用。换句话说,我们不关心在运行时何时以及何时调用AsyncTask.onPostExecute(),我们只需要保证它将在最后的某个阶段被调用。这就是为什么这个方法不返回执行结果的原因 - 相反,它要求执行结果作为doInBackground()中唯一的方法参数传入。
此外,Android API提供了一种在编码时{@ 3}}返回AsyncTask执行结果的方法:
MyAsyncTask myAsyncTask = new MyAsyncTask();
// This must be called from the UI thread:
myAsyncTask.execute();
// Calling this will block UI thread execution:
ExecutionResult result = myAsyncTask.get();
请记住,AsyncTask.get()将阻止调用线程的执行,如果你在UI线程上调用它,你可能会得到一个ANR异常。这是使用AsyncTask的有效负载.get(),通过在UI线程上调用它,实际上是使AsyncTask(工作线程)与UI线程同步运行(通过使UI线程等待)。总而言之,这是可行的,但不推荐。
答案 2 :(得分:1)
仅供将来参考,因为这篇文章有点旧:
我创建了一个Activity类,它有一个onStart()方法和一个单独的AsyncTask类。根据我的测试,在doInbackground()方法之后,结果将首先发送到活动,然后运行onPostExecute()。这是因为基于logcat,我首先得到了我的第一个响应数据(由服务器发送),然后这个响应将再次显示在活动中,并且onPostExecute()中的最后一个消息将显示。
活动代码:
@Override
protected void onStart() {
super.onStart();
String str = "***";
if(isConnectedToInternet()){
myAsyncTask.execute();
try {
if(myAsyncTask.get())
str = myAsyncTask.getResponseMsg();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (CancellationException e) {
e.printStackTrace();
}
}
Log.i("Data returned by server2:", str);
}
AsyncTask代码:
public class MyAsyncTask extends AsyncTask<Void, Void, Boolean> {
private URL url;
private HttpURLConnection conn;
private String strResponseMsg;
public MyAsyncTask(String url) throws MalformedURLException{
this.url = new URL(url);
}
@Override
protected void onPreExecute() {
Log.i("Inside AsyncTask", "myAsyncTask is abut to start...");
}
@Override
protected Boolean doInBackground(Void... params) {
boolean status = false;
try {
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(Manager.ConnTimeout);
conn.setReadTimeout(Manager.ReadTimeout);
int responseCode = conn.getResponseCode();
Log.i("Connection oppened", "Response code is:" + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
if (in != null) {
StringBuilder strBuilder = new StringBuilder();
// Read character by character
int ch = 0;
while ((ch = in.read()) != -1)
strBuilder.append((char) ch);
// Showing returned message
strResponseMsg = strBuilder.toString();
Log.i("Data returned by server:", strResponseMsg);
status = true;
}
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return status;
}
@Override
protected void onPostExecute(Boolean result) {
Log.i("Inside AsyncTask", "myAsyncTask finished its task. Returning data to caller...");
}
public String getResponseMsg(){
return strResponseMsg;
}
}