安卓开发——okhttp的使用
项目采用的结构为Android客户端+django服务端的方式,而其之间需要一个通信的桥梁,这就使用到了http。
http协议格式简介
-
可以看到,我们的请求消息中包括了路由(也就是url),请求消息头(就是一堆键值对,可以添加请求时所附带的信息,比如账号,坐标等要服务器处理的信息),请求体不需要我们操作,就是封装了一些请求参数
如果想具体了解http请求请阅HTTP完全注解,这个文章详细讲解了http请求的每部分。
OKHTTP示例:
安卓部代码:
public void get_new_workmates() {
String url = ServerSetting.ServerPublicIpAndPort+"driver_get_workmates/";
OkHttpClient okHttpClient = new OkHttpClient(); //构建一个网络类型的实例
RequestBody requestBody = new FormBody.Builder()
.add("driver_account", driver_account)
.build();
Request request = new Request.Builder() //构建一个具体的网络请求对象,具体的请求url,请求头,请求体等
.url(url)
.post(requestBody)
.build();
Call call = okHttpClient.newCall(request); //将具体的网络请求与执行请求的实体进行绑定
call.enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
requireActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(requireActivity(), "获取失败:请检查网络", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onResponse(@NonNull Call call, @NonNull okhttp3.Response response) throws IOException {
if (!response.isSuccessful()&&response.body() != null) {
// 请求不成功,处理错误响应
final String errorMessage = response.body().string();
// 切换到主线程更新 UI
requireActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(requireActivity(), "获取失败:" + errorMessage, Toast.LENGTH_SHORT).show();
}
});
} else {
String workmates_name,workmates_account,workmates_latitude,workmates_longitude;
BitmapDescriptor driver_picture = BitmapDescriptorFactory.fromResource(R.drawable.driver_mates);
try {
if (response.body() != null){
clean_last_workmates(); //清除之前的同事位置
JSONArray jsonArray =new JSONArray(response.body().string()); //将string类型的response转换为JSONObject类型的object
for(int i=0;i<jsonArray.length();i++)
{
JSONObject object = jsonArray.getJSONObject(i);
workmates_name=object.getString("name");
workmates_account=object.getString("account");
workmates_latitude=object.getString("latitude");
workmates_longitude=object.getString("longitude");
double latitude=Double.parseDouble(workmates_latitude);
double longitude=Double.parseDouble(workmates_longitude);
//Log.e("TAG?!?!?!?!", "run: "+ latitude+longitude);
workmates_List.add(new MarkerOptions().position(new LatLng(latitude,longitude)).title("workers").icon(driver_picture).snippet(workmates_name));
}
if(SHOWorNOT_SHOW==1) //若还处于展示阶段
{
requireActivity().runOnUiThread(new Runnable() { //在主线程处理绘制任务
@Override
public void run() {
print_new_workmates(); //绘制新的同事位置
}
});
}
handler.postDelayed(Show_workmatesRunnable, 5000);
}
} catch (JSONException e) {
throw new RuntimeException(e);
}
//Toast.makeText(getActivity(), "查找成功", Toast.LENGTH_SHORT).show();
}
}
});
}
-
现在对上面代码进行解读:首先创建okhttp实体,然后创建一个网络请求对象,其中包括请求头中需要的路由(url),请求体中的键值对。我们要把需要传输的参数写在键值对上。最后用call将该网络请求与okhttp实体绑定。然后用call.enqueue发送并异步地执行网络请求,然后就可以重写其中的回调函数了。
-
在重写的回调中,在请求失败时调用onFailure方法,在这里我们应该转到主线程并用toast弹出请求失败的错误(UI的更新要在主线程中,不然会引起程序崩溃等问题),这个onfailure通常是由于网络问题,后面我们可以在onResponse中找到我们自己书写的错误:HttpResponseServerError('错误内容')
-
在重写的回调中,在请求成功时调用onResponse方法,这里的
if (!response.isSuccessful()&&response.body() != null)
说明django返回了HttpResponseServerError('错误内容'),我们在下方解析相应体中的字符串即可获得‘错误内容’中的东西。如果成功相应,就执行else后的内容。切记在执行UI更新操作时要切换到主线程。
上面的示例中用hander不断发送请求来获得同事位置(写到这里突然意识到可能出现递而不归的情况,抓紧改bug,把hander放在主线程,通过监听全局变量来发送hander延迟请求,请求结束时影响全局变量即可)。
django部分代码:
def driver_get_workmates(request): #获取司机同事信息
if request.method=='POST':
driverGet=request.POST.get('driver_account', '')
driver_line_get=Driver.objects.get(account=driverGet).driver_line
driver_school_get=Driver.objects.get(account=driverGet).driver_school
line_id_get=Bus_line.objects.get(line_name=driver_line_get,line_school=driver_school_get).line_id
with connection.cursor() as cursor:
cursor.execute("select * from driver_and_location \
where driver_line_id=%s \
and isworking=%s and account!=%s",[line_id_get,1,driverGet])
columns = [col[0] for col in cursor.description]
results = [dict(zip(columns, row)) for row in cursor.fetchall()]
#results = cursor.fetchall()
#print(results)
res=[
{
'name':result['name'],
'account':result['account'],
'latitude':result['latitude'],
'longitude':result['longitude'],
}
for result in results
]
#print(res)
return JsonResponse(res,safe=False)
#return HttpResponseServerError('账号不存在')
-
这里可以看到我通过访问数据库获取了同线路的其他同事的详细信息并打包返回。我没有使用
HttpResponseServerError,因为没必要,这个给了注释,如果需要可以照猫画虎。
以上就是安卓开发中的一个通信部分的示例了。希望对大家有帮助。