【问题标题】:Android, Web Services, AsyncTask please help a noob/make sure im starting rightAndroid、Web 服务、AsyncTask 请帮助一个菜鸟/确保我开始正确
【发布时间】:2012-03-26 08:57:04
【问题描述】:

自原始帖子以来我已经进行了编辑我正在制作一个连接到 JSON API 的 Android 应用程序。到目前为止一切正常,除非服务器有延迟。如果时间过长,用户界面当然会停止响应。我读过 asynctask 可以解决我的问题。不过,我在这些例子上度过了一段非常愉快的时光。

这是进行 http 调用的 restclient 类...解析 json 并将自定义对象存储到我的其他类可以访问的公共列表中。

package com.bde.dgcr;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.widget.ListView;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class RestClient {
static List<ResponseHolder> list = new ArrayList<ResponseHolder>();
protected Context context = this.context;

private static String convertStreamToString(InputStream is) {
    /*
       * To convert the InputStream to String we use the BufferedReader.readLine()
       * method. We iterate until the BufferedReader return null which means
       * there's no more data to read. Each line will appended to a StringBuilder
       * and returned as String.
       */
    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    StringBuilder sb = new StringBuilder();

    String line = null;
    try {
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return sb.toString();
}


/* This is a test function which will connects to a given
  * rest service and prints it's response to Android Log with
  * labels "Praeda".
  */
public void  connect(String url) {


    AsyncTask<String, Void, Void> connection = new AsyncTask<String, Void, Void>() {
        protected Context context;
        @Override
        protected Void doInBackground(String... params) {
// Prepare a request object
            HttpGet httpget = new HttpGet(params[0]);

// Execute the request
            HttpResponse response;
            HttpClient httpclient = new DefaultHttpClient();
            try {
                list.clear();
                response = httpclient.execute(httpget);
                // Examine the response status
                Log.i("Praeda", response.getStatusLine().toString());

                // Get hold of the response entity
                HttpEntity entity = response.getEntity();
                // If the response does not enclose an entity, there is no need
                // to worry about connection release

                if (entity != null) {

                    // A Simple JSON Response Read
                    InputStream instream = entity.getContent();
                    String result = convertStreamToString(instream);

                    // A Simple JSONObject Creation
                    //JSONObject json= new JSONObject(result);
                    JSONArray jsonArray = new JSONArray(result);


                    // A Simple JSONObject Parsing
                    for (int i = 0; i < (jsonArray.length()); i++) {
                        JSONObject json_obj = jsonArray.getJSONObject(i);
                        ResponseHolder rh = new ResponseHolder(json_obj);
                        list.add(rh);
                    }


                    instream.close();

                }

            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
             ListView listView1;


            super.onPostExecute(aVoid);    //To change body of overridden methods use       File | Settings | File Templates.
            ResponseHolderAdapter adapter = new ResponseHolderAdapter(context, R.layout.listview_item_row, RestClient.list);
            listView1 = (ListView) findViewById(R.id.listView1);

            View header = (View)         getLayoutInflater().inflate(R.layout.listview_header_row, null);
            listView1.addHeaderView(header);

            listView1.setAdapter(adapter);
        }
    };
    connection.execute(url);

}
}

这是调用静态连接方法并使用列表让适配器进入列表视图的类。

public class JsonGrabber extends Activity {


private final String API_KEY = "key";
private final String SECRET = "secret";
private String state;
private String city;
private String country;
private static String mode;
private String md5;
private String url;
CourseSearch cs;
private ListView listView1;

/**
 * Called when the activity is first created.
 */


public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.results);
    Bundle extras = getIntent().getExtras();
    state = extras.getString("state");
    city = URLEncoder.encode(extras.getString("city"));
    country = extras.getString("country");
    mode = extras.getString("mode");
    md5 = MD5.getMD5(API_KEY + SECRET + mode);
    System.out.println(md5);
    url = "http://www.api.com/?key=" + API_KEY + "&mode=" + mode + "&id=1&sig=" + md5;
    String findByLocUrl = "http://www.api.com/?key=" + API_KEY + "&mode=" + mode + "&city=" + city + "&state=" + state + "&country=" + country + "&sig=" + md5;
    System.out.println(findByLocUrl);
    RestClient rc = new RestClient();
    rc.connect(findByLocUrl);
    //RestClient.connect(findByLocUrl);
/*        if (RestClient.list.isEmpty())
    {
        setContentView(R.layout.noresults);
    }     else
    {

    ResponseHolderAdapter adapter = new ResponseHolderAdapter(this, R.layout.listview_item_row, RestClient.list);
    listView1 = (ListView) findViewById(R.id.listView1);

    View header = (View) getLayoutInflater().inflate(R.layout.listview_header_row, null);
    listView1.addHeaderView(header);

    listView1.setAdapter(adapter);
    }

 */
}


}

我应该以某种方式将所有这一切融入使用扩展 asyctask 的内部类在后台执行 API 调用解析 json 添加到我的列表并设置适配器。我知道我可能有一些面向对象的问题,并希望在我继续使用我的应用程序之前,你们可以确保我朝着正确的方向前进。我还有其他一些我没有包括在内的课程。让我知道如果我添加其他类是否更有意义。提前感谢你们可以提供的任何帮助。

【问题讨论】:

    标签: java android oop android-asynctask


    【解决方案1】:

    您可以像这样使用 AsyncTask 重写您的连接方法:

    public static void connect(String url) {
    
    HttpClient httpclient = new DefaultHttpClient();
    
    AsyncTask<String, Void, Void> connection = new AsyncTask<String, Void, Void>() {
    
    @Override
    protected Void doInBackground(String... params) {
    // Prepare a request object
    HttpGet httpget = new HttpGet(params[0]);
    
    // Execute the request
    HttpResponse response;
    try {
        list.clear();
    
        response = httpclient.execute(httpget);
        // Examine the response status
        Log.i("Praeda", response.getStatusLine().toString());
    
        // Get hold of the response entity
        HttpEntity entity = response.getEntity();
        // If the response does not enclose an entity, there is no need
        // to worry about connection release
    
        if (entity != null) {
    
            // A Simple JSON Response Read
            InputStream instream = entity.getContent();
            String result= convertStreamToString(instream);
    
        // A Simple JSONObject Creation
        //JSONObject json= new JSONObject(result);
        JSONArray jsonArray = new JSONArray(result);
    
    
        // A Simple JSONObject Parsing
        for (int i = 0; i < (jsonArray.length()); i++) {
            JSONObject json_obj = jsonArray.getJSONObject(i);
            ResponseHolder rh = new ResponseHolder(json_obj);
            list.add(rh);
        }
    
    
         instream.close();
        }
        }
        } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    
    connection.execute(url);
    }
    

    【讨论】:

    • 谢谢。我试图使用它,但我认为有一些右括号错误。现在尝试修复它们,并让您知道它是如何工作的
    • 所以这确实有效,但唯一的问题是适配器工作永远不会发生。我的列表视图永远不会填充它只显示标题的行项目。当我关闭显示器然后打开时,它会在我的列表视图中显示结果。我需要将适配器代码移动到 onPostExecute 吗?
    • 是的,您应该为此使用 onPostExecute 方法。任何 UI 更新都应该在 onPreExecute 和 onPostExecute 中完成。
    • 我试过这样做,但我认为我得到了 null,因为 asynctask 所在的类是一个非活动类,并且我在获取传递给适配器类的上下文时遇到问题。
    【解决方案2】:

    如果你想把它做好,你应该使用内容提供者、服务和数据库,这里有一个很好的教程:

    http://mobile.tutsplus.com/tutorials/android/android-fundamentals-downloading-data-with-services/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-25
      • 2012-08-18
      • 2011-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多