带参数的asynctask
很多时候,我们需要使用AsyncTask填充Listview 。 当我们必须调用远程服务器并使用JSON交换信息时,就是这种情况。
在这篇文章中,我想更深入地研究ListView 。 在之前的文章中,我描述了如何使用标准和自定义适配器以几种方式使用ListView。 在所有示例中,我应该设置一个固定的项目。 在这篇文章中,我将描述如何直接从JEE Server中检索项目。
为了简单起见,我们假设我们有一个简单的JEE服务器来管理某些联系人。 我们的联系方式是:姓名,姓氏,电子邮件和电话号码。 如何使该服务器不在本文的讨论范围之内,我将仅提供源代码。 为了给您提供一些细节,我可以说该服务器是使用RESTFul Webservices开发的JEE服务器(在我们的案例jersey api中)。
在这种情况下,该应用程序的行为类似于客户端,该客户端调用remove服务以获取联系人列表并使用ListView对其进行显示。 从服务器传递到客户端的数据使用JSON格式化。
与往常一样,我们开始创建使用自定义布局的自定义适配器。 如果您需要有关创建自定义适配器的更多信息,可以在这里和这里看看。 这是代码:
public class SimpleAdapter extends ArrayAdapter<Contact> {
private List<Contact> itemList;
private Context context;
public SimpleAdapter(List<Contact> itemList, Context ctx) {
super(ctx, android.R.layout.simple_list_item_1, itemList);
this.itemList = itemList;
this.context = ctx;
}
public int getCount() {
if (itemList != null)
return itemList.size();
return 0;
}
public Contact getItem(int position) {
if (itemList != null)
return itemList.get(position);
return null;
}
public long getItemId(int position) {
if (itemList != null)
return itemList.get(position).hashCode();
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.list_item, null);
}
Contact c = itemList.get(position);
TextView text = (TextView) v.findViewById(R.id.name);
text.setText(c.getName());
TextView text1 = (TextView) v.findViewById(R.id.surname);
text1.setText(c.getSurname());
TextView text2 = (TextView) v.findViewById(R.id.email);
text2.setText(c.getEmail());
TextView text3 = (TextView) v.findViewById(R.id.phone);
text3.setText(c.getPhoneNum());
return v;
}
public List<Contact> getItemList() {
return itemList;
}
public void setItemList(List<Contact> itemList) {
this.itemList = itemList;
}
}
到现在为止,一切都变得顺畅而轻松。
HTTP客户端
我们需要做的一件事就是创建我们的HTTP客户端,以便向JEE服务器发出请求。 众所周知,在获得答案之前,HTTP请求可能需要很长时间,因此我们需要将其考虑在内,以便Android OS不会停止我们的应用程序。 最简单的操作是创建一个AsyncTask ,该AsyncTask发出此请求并等待响应。
private class AsyncListViewLoader extends AsyncTask<String, Void, List<Contact>> {
private final ProgressDialog dialog = new ProgressDialog(MainActivity.this);
@Override
protected void onPostExecute(List<Contact> result) {
super.onPostExecute(result);
dialog.dismiss();
adpt.setItemList(result);
adpt.notifyDataSetChanged();
}
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog.setMessage("Downloading contacts...");
dialog.show();
}
@Override
protected List<Contact> doInBackground(String... params) {
List<Contact> result = new ArrayList<Contact>();
try {
URL u = new URL(params[0]);
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setRequestMethod("GET");
conn.connect();
InputStream is = conn.getInputStream();
// Read the stream
byte[] b = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ( is.read(b) != -1)
baos.write(b);
String JSONResp = new String(baos.toByteArray());
JSONArray arr = new JSONArray(JSONResp);
for (int i=0; i < arr.length(); i++) {
result.add(convertContact(arr.getJSONObject(i)));
}
return result;
}
catch(Throwable t) {
t.printStackTrace();
}
return null;
}
private Contact convertContact(JSONObject obj) throws JSONException {
String name = obj.getString("name");
String surname = obj.getString("surname");
String email = obj.getString("email");
String phoneNum = obj.getString("phoneNum");
return new Contact(name, surname, email, phoneNum);
}
}
让我们分析一下代码。
在任务开始之前的第一步( onPreExecute() )中,我们仅显示一个对话框以通知用户该应用程序正在下载联系人列表。 最有趣的部分是在doInBackground方法中,应用程序通过该方法建立HTTP连接。 我们首先创建一个HTTPConnection,然后像这样设置GET方法:
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setRequestMethod("GET");
conn.connect();
接下来,我们创建一个输入流,然后读取字节流:
InputStream is = conn.getInputStream();
// Read the stream
byte[] b = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ( is.read(b) != -1)
baos.write(b);
现在我们将所有流都保存在字节数组中,我们只需要使用JSON对其进行解析。
JSONArray arr = new JSONArray(JSONResp);
for (int i=0; i < arr.length(); i++) {
result.add(convertContact(arr.getJSONObject(i)));
}
return result;
做完了! 接下来是什么?…我们需要通知适配器我们有新的联系人列表,并且必须显示它。 我们可以在onPostExecute(List <Contact> result)中做到这一点:
super.onPostExecute(result);
dialog.dismiss();
adpt.setItemList(result);
adpt.notifyDataSetChanged();
翻译自: https://www.javacodegeeks.com/2013/06/android-asynctask-listview-json.html
带参数的asynctask