从 AsyncTask Android 返回数据 [英] Return data from AsyncTask Android

查看:20
本文介绍了从 AsyncTask Android 返回数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在 SO 上参考类似的问题,但没有得到任何帮助.

在我的 android 应用程序中,我计划实施用户访问过的最近报价,即类似于最近访问过的网页页面.

以下是我正在执行的步骤:

1.) 每当用户打开任何公司视图时,从数据库中获取公司符号

2.) 然后将当前符号与日期时间一起存储在数据库中.

3.) 对于从数据库中获取的所有符号,获取它们的当前值%Change并显示公司名称,当前值和 %Change 在列表中.

问题出现在 ASyncTask 类中,因为 postExecute 方法不允许它的返回类型为 void 以外的任何类型.>

我做错了什么吗?

任何帮助都可以挽救生命!!!

String[] rsym,rcmp,rchg;rdbM = 新的RecentDBManager(CompanyView.this);尝试 {日历日期1 = Calendar.getInstance();SimpleDateFormat dateformatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");String currentdate = dateformatter.format(date1.getTime());rdbM.openDB();//步骤1rsym = rdbM.getRecent_sym();//第2步rdbM.setData(currentsymbol, currentdate);rdbM.closeDB();} 捕获(异常 e){throw new Error(" *** ERROR in DB Access *** "+ e.toString());}//第3步for(int i=0;i<rsym.length;i++){DownloadRecentQuote quotetask = new DownloadRecentQuote();最近报价任务.execute(new String[] { "http://abc.com/stockquote.aspx?id="+ rsym[i] });//CURRENT VALUE 和 %CHANGE 应该从 ASyncTask 类返回rcmp[i]=valuearr[0];rchg[i]=valuearr[1];}list1 = new ArrayList>();HashMap<字符串,字符串>添加列表1;for (int i = 0; i < limit; i++){addList1 = new HashMap();addList1.put(RecentSym_COLUMN, rsym[i]);addList1.put(RecentCMP_COLUMN, rcmp[i]);addList1.put(RecentChg_COLUMN, rchg[i]);list1.add(addList1);最近的适配器适配器 1 = 新的最近的适配器(CompanyView.this, CompanyView.this, list1);listrecent.setAdapter(adapter1);}私有类 DownloadRecentQuote 扩展了 AsyncTask{/* 获取最近报价信息的数据 */@覆盖受保护的字符串 doInBackground(String... urls) {字符串响应 = "";对于(字符串网址:网址){DefaultHttpClient 客户端 = 新的 DefaultHttpClient();HttpGet httpGet = new HttpGet(url);尝试 {HttpResponse 执行 = client.execute(httpGet);InputStream content = execute.getEntity().getContent();BufferedReader 缓冲区 = 新的 BufferedReader(新的 InputStreamReader(content));字符串 s = "";while ((s = buffer.readLine()) != null) {响应 += s;}} 捕获(异常 e){e.printStackTrace();}}返回响应;}@覆盖protected void onPostExecute(String result) {arr1 = result.split("@");如果 (arr1[0].length() != 0) {如果 (arr1[0].equals("1")) {arr = arr1[1].split(";");//返回2个字符串字符串值arr[];值arr[0] = arr[3];valuearr[1] = arr[6].concat("%");//返回值arr;}}}

解决方案

postExecute() 无法返回值,因为它会返回给谁或什么?您调用 AsyncTask 的原始方法已经消失,因为您的 AsyncTask 在后台运行.它是异步的,当 AsyncTask.execute() 返回时它仍然在后台运行,因此 postExecute() 不能返回值,因为没有什么可以返回它.

相反,您的 AsyncTask 需要引用回您的 Activity 或某个其他对象,以便它可以将您的值发回给它.在您的代码中,您调用 execute() 之后的行不能存在,因为您的任务尚未完成.相反,您应该创建一个名为 updateSymbol( currentPrice, percentChange) 的方法,将 execute() 下的所有代码移到那里,并且在您的 AsyncTask 中,您应该传递对 Activity 的引用.然后从 onPostExecute() 方法调用 updateSymbol( currentPrice, percentChange ).

但是,如果您有一个对活动的引用,请小心,当您的 doInBackground() 运行时它可以被销毁,并且当 postExecute() 运行时,它应该只删除结果或不尝试更新 UI.例如,用户旋转他们的手机导致 Activity 被销毁.我发现最好在活动中保留对 AsyncTask 的引用,以便在活动被销毁时可以取消()它.您可以调用 AsyncTask.cancel() 然后检查您的任务是否被取消,例如:

public void postExecute(String result) {如果(!isCanceled()){//在这里做你的更新活动.setSymbol(结果);}}

为所有活动创建基类真的很容易,这样您就可以轻松跟踪 AsyncTask 的运行情况:

公共类 BaseActivity 扩展 Activity {列表运行任务;公共无效 onStop() {for(异步任务任务:runningTasks){任务.取消(真);}}公共异步任务开始(异步任务任务){runningTasks.add( 任务);返回任务;}公共无效完成(异步任务任务){runningTasks.remove( 任务);}}

一些快速提示.你不需要 execute( new String[] { "blah" + blah } ).Java 中的可变参数允许您执行此操作.执行(等等"+ 等等).您还可以捕获异常并继续处理,而没有真正处理它们.当某些事情真的发生时会很困难,因为您的应用程序会捕获它们,然后就好像什么也没发生一样继续.如果出现错误,您可能希望向用户提供一些反馈并停止尝试执行该过程.停下来,向用户展示一个错误,让他们做下一件事情.将 catch 块移到方法的底部.

I tried to refer similar question on SO, but didn't got any help.

In my android app, I'm planning to implement Recent Quote the user has visited i.e. similar to recently visited pages on web.

Following are the steps I'm following:

1.) Whenever user opens any company view, fetch the company symbols from database

2.) Then store the current symbol along with dateTime in database.

3.) For all symbols fetched from database, Fetch their current value and %Change and display Company name, current value and %Change in a list.

The problem arises in the ASyncTask class as postExecute method doesn't allow it's return type to be any other than void.

Am I doing anything wrong?

Any help will be life saver !!!

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

解决方案

postExecute() can't return a value because who or what would it return to? Your original method that invoked the AsyncTask is gone because your AsyncTask is running in the background. It's asynchronous meaning when AsyncTask.execute() returns it's still running in the background, and hence postExecute() can't return a value because there's nothing to return it to.

Instead your AsyncTask needs a reference back to your Activity or some other object so it can post your values back to it. In your code the lines after you call execute() can't be there because your task hasn't finished. Instead you should create a method called updateSymbol( currentPrice, percentChange), move all that code below execute() in there, and in your AsyncTask you should pass a reference to the Activity. Then call updateSymbol( currentPrice, percentChange ) from the onPostExecute() method.

But, be careful if you have a reference back to an Activity it can be destroyed while your doInBackground() is running, and when postExecute() runs it should just drop the results or not attempt to update the UI. For example, the user rotates their phone causing the Activity to be destroyed. I find it best to hold a reference to the AsyncTask in the activity so it can cancel() it if the Activity is destroyed. You can call AsyncTask.cancel() then check if your task was canceled like:

public void postExecute( String result ) {
    if( !isCanceled() ) {
       // do your updating here
       activity.setSymbol( result );
    }
}

It's really easy to create a base class for all Activities so you can easily keep track of AsyncTasks running:

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

Some quick pointers. You don't need execute( new String[] { "blah" + blah } ). Varargs in Java allow you to do this. execute( "blah" + blah ). You also are catching exceptions and continuing without really handling them. It will be hard when something really happens because your app catches them, and just continues as if nothing happened. If you get an error you might want to provide some feedback to the user and stop trying to execute that process. Stop, show an error to the user, and let them do the next thing. Move the catch blocks to the bottom of the methods.

这篇关于从 AsyncTask Android 返回数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆