看完本文,您可以学到:
1.Android与后台交互的模板化方法
2.JSON的使用
3.检查网络连接
4.AsyncTask的使用
我们简单的以登录为例,来实现整个的流程。话不多说,先来看看效果图:
一、通用类的编写
首先,既然要实现交互模板化,最重要的就是要提取出尽可能多的可复用代码。无论是与后台进行什么操作,判断网络是否正常连接、发送请求后得到数据、网络异常时的错误信息提示都是必不可少的。所以我们编写一个通用的CallService类:
-
-
-
-
public class CallService {
-
-
-
-
-
-
-
-
private static boolean checkNet(Context context) {
-
ConnectivityManager connectivity = (ConnectivityManager) context
-
.getSystemService(Context.CONNECTIVITY_SERVICE);
-
if (connectivity != null) {
-
-
NetworkInfo info = connectivity.getActiveNetworkInfo();
-
if (info != null && info.isConnected()) {
-
-
if (info.getState() == NetworkInfo.State.CONNECTED) {
-
return true;
-
}
-
}
-
}
-
return false;
-
}
-
-
-
-
-
-
-
-
-
public static String call(String urlString, String content, Context context) {
-
if (!checkNet(context)) {
-
return null;
-
}
-
try {
-
URL url = new URL(urlString);
-
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
-
conn.setConnectTimeout(5000);
-
conn.setDoOutput(true);
-
conn.setRequestMethod("POST");
-
conn.setRequestProperty("User-Agent", "Fiddler");
-
conn.setRequestProperty("Content-Type", "application/json");
-
conn.setRequestProperty("Charset", "utf-8");
-
OutputStream os = conn.getOutputStream();
-
os.write(content.getBytes());
-
os.close();
-
int code = conn.getResponseCode();
-
if (code == 200) {
-
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
-
String retData;
-
String responseData = "";
-
while ((retData = in.readLine()) != null) {
-
responseData += retData;
-
}
-
in.close();
-
return responseData;
-
}
-
} catch (MalformedURLException e) {
-
e.printStackTrace();
-
} catch (UnsupportedEncodingException e) {
-
e.printStackTrace();
-
} catch (ProtocolException e) {
-
e.printStackTrace();
-
} catch (IOException e) {
-
e.printStackTrace();
-
}
-
return null;
-
}
-
-
public static void showNetErr(Context context){
-
new AlertDialog.Builder(context)
-
.setTitle("网络错误")
-
.setMessage("网络连接失败,请确认网络连接")
-
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
-
@Override
-
public void onClick(DialogInterface arg0, int arg1) {
-
-
}
-
}).show();
-
}
-
-
}
其中,判断网络连接状态是借助Android系统提供的ConnectivityManager的方法实现的,借助这个类我们还可以获取更多的连接状态信息,包括当前是用流量还是WIFI等等。
然后,在调用本类核心方法call()时,传入了三个参数,一个是后台服务的url路径,一个是已经组装好的参数,第三个是上下文context。
在这个方法中,我们先去判断网络连接,未连接就直接返回空。否则就使用HttpURLConnection方法向服务器发送请求,再把服务器的返回值返回给调用者。
另一个showNetErr方法就只是简单地跳出一个对话框进行提示。
二、利用Json以及AsyncTask进行交互
我们都知道,在安卓中进行网络操作等等这些耗时的操作,都不能在主线程(即UI线程中)操作,所以我们利用安卓提供的异步机制
AsyncTask(或者也可以自己写new Thread +
Handler)来进行网络操作。
我们以登录为例:
-
-
-
-
-
public class Login {
-
-
private static final String urlString = GetServerUrl.getUrl() + "index.php?r=period/login";
-
private static final String TAG = "Login";
-
-
private ProgressBar progressBar;
-
private Context context;
-
-
private String userName;
-
private String password;
-
-
public Login( Context context,ProgressBar progressBar) {
-
this.progressBar=progressBar;
-
this.context = context;
-
}
-
-
public void login(String userName,String password) {
-
Log.i(TAG, "call login");
-
this.userName=userName;
-
this.password=password;
-
new LoginTask().execute();
-
}
-
-
class LoginTask extends AsyncTask<Void, Void, String> {
-
@Override
-
protected String doInBackground(Void... params) {
-
JSONObject tosendsObject = new JSONObject();
-
Log.i(TAG, "start put json!");
-
try {
-
-
tosendsObject.put("username", userName);
-
tosendsObject.put("password", password);
-
} catch (JSONException e) {
-
e.printStackTrace();
-
}
-
-
String content = String.valueOf(tosendsObject);
-
Log.i(TAG, "send :" + content);
-
String responseData = CallService.call(urlString, content,context);
-
if(responseData==null || responseData.equals("")){
-
return null;
-
}
-
Log.i(TAG, "res:" + responseData);
-
JSONObject resultObject = null;
-
String result=null;
-
try {
-
resultObject = new JSONObject(responseData);
-
result = resultObject.getString("result");
-
Log.i(TAG, "result:" + result);
-
} catch (JSONException e) {
-
e.printStackTrace();
-
}
-
return result;
-
}
-
-
@Override
-
protected void onPreExecute() {
-
progressBar.setVisibility(View.VISIBLE);
-
super.onPreExecute();
-
}
-
-
@Override
-
protected void onPostExecute(String result) {
-
progressBar.setVisibility(View.GONE);
-
if(result==null){
-
CallService.showNetErr(context);
-
return;
-
}
-
Toast.makeText(context,"result:"+result,Toast.LENGTH_SHORT).show();
-
-
}
-
}
-
}
我们在LoginActivity中初始化这个类的实例,传入上下文以及ProgressBar(用于提高用户体验),再调用login方法传入用户名和
密码这两个参数。在进行操作前,onPreExecute方法显示出ProgressBar,在返回结果后,onPostExecute方法再隐藏
ProgressBar。
然后我们再看doInBackGroud方法(这个方法听名字就是异步操作啊):我们创建一个JsonObject对象,再使用键值对的方法
(类似map)传入参数,最后转成String后一起传给服务器。在得到结果后把服务器返回的json形式的字符串转成JsonObject。如果返回的
是空,说明连接有问题,就调用通用类的showNetErr方法。
我把Log截了图,此前不清楚Json格式的朋友可以管中窥豹:
如果有需要传一个list给服务器,还可以使用JsonArray类。比如:
-
JSONArray jsonArray = new JSONArray();
-
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
-
try {
-
for (PeriodPO peroid : localPeriods) {
-
JSONObject periodObject = new JSONObject();
-
periodObject.put("date", sdf.format(peroid.getDate()));
-
periodObject.put("tag", peroid.getTag());
-
periodObject.put("length", peroid.getLength());
-
jsonArray.put(periodObject);
-
}
-
tosendsObject.put("periods", jsonArray);
-
-
tosendsObject.put("username", "test");
-
} catch (JSONException e) {
-
e.printStackTrace();
-
}
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。