本章讲述在android开发中,常用的网络请求操作。网络请求利用android基本的HttpURLConnection连接URL和开源网络请求包AsyncHttpClient。本次网络请求以调取天气接口查询天气为案例,对请求到的天气数据采用SQLite数据库存储,并利用ContentProvider数据共享模式操作存储数据。本章主要介绍知识点HttpURLConnection,AsyncHttpClient,ContentProvider,Json解析插件GsonFormat及Json解析类Gson。
做一个天气应用
图1
图2
图3
简要说明:启动软件,通过图1界面可以选择查询天气的城市,点击查询直接查询该城市最近一周的天气指数,通过图3,下拉页面可重新请求刷新对应城市的天气指数。
ContentProvider(内容提供者)是Android中的四大组件之一。主要用于对外共享数据,也就是通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider对指定应用中的数据进行操作。ContentProvider分为系统的和自定义的,系统的也就是例如联系人,图片等数据。
内容提供者将一些特定的应用程序数据供给其它应用程序使用。数据可以存储于文件系统、 SQLite数据库或其它方式。内容提供者继承于ContentProvider 基类,为其它应用程序取用和存储它管理的数据实现了一套标准方法。然而,应用程序并不直接调用这些方法,而是使用一个 ContentResolver 对象,调用它的方法作为替代。ContentResolver可以与任意内容提供者进行会话,与其合作来对所有相关交互通讯进行管理。
3.ContentResolver用法
当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver类来完成,要获取ContentResolver对象,可以使用Context提供的getContentResolver()方法。 ContentResolver提供的方法和ContentProvider提供的方法对应的有以下几个方法。
在Content Provider中使用的查询字符串有别于标准的SQL查询。很多诸如select, add, delete, modify等操作我们都使用一种特殊的URI来进行,这种URI由3个部分组成, “content://”, 代表数据的路径,和一个可选的标识数据的ID。以下是一些示例URI:
标准Java接口(java.net) ,HttpURLConnection,可以实现简单的基于URL请求、响应功能;基本操作如下:
1 //创建一个URL对象 2 URL url = new URL(http://www.baidu.com); 3 //利用HttpURLConnection对象从网络中获取网页数据 4 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 5 //设置连接超时 6 conn.setConnectTimeout(6*1000); 7 //对响应码进行判断 8 if (conn.getResponseCode() != 200) //从Internet获取网页,发送请求,将网页以流的形式读回来 9 throw new RuntimeException("请求url失败"); 10 //得到网络返回的输入流 11 InputStream is = conn.getInputStream(); 12 //String result = readData(is, "GBK"); //文件流输入出文件用outStream.write 13 //conn.disconnect();
An asynchronous callback-based Http client for Android built on top of Apache’s HttpClient libraries. All requests are made outside of your app’s main UI thread, but any callback logic will be executed on the same thread as the callback was created using Android’s Handler message passing.( 异步基于回调的Http客户端为Android构建,是基于Apache HttpClient库的。所有的请求都是位于应用程序主线程 UI 之外,但任何回调逻辑将相同的线程上执行回调,使用Android的处理程序创建消息传递。)官网地址:http://loopj.com/android-async-http
1 AsyncHttpClient client = new AsyncHttpClient(); 2 client.get("https://www.google.com", new AsyncHttpResponseHandler() { 3 4 @Override 5 public void onStart() { 6 // called before request is started 7 } 8 9 @Override 10 public void onSuccess(int statusCode, Header[] headers, byte[] response) { 11 // called when response HTTP status is "200 OK" 12 } 13 14 @Override 15 public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) { 16 // called when response HTTP status is "4XX" (eg. 401, 403, 404) 17 } 18 19 @Override 20 public void onRetry(int retryNo) { 21 // called when request is retried 22 } 23 });
1 //Create empty RequestParams and immediately add some parameters: 2 RequestParams params = new RequestParams(); 3 params.put("key", "value"); 4 params.put("more", "data"); 5 //Add a File object to the RequestParams to upload: 6 File myFile = new File("/path/to/file.png"); 7 RequestParams params = new RequestParams(); 8 try { 9 params.put("profile_picture", myFile); 10 } catch(FileNotFoundException e) {} 11 //Add a byte array to the RequestParams to upload: 12 byte[] myByteArray = blah; 13 RequestParams params = new RequestParams(); 14 params.put("soundtrack", new ByteArrayInputStream(myByteArray), "she-wolf.mp3"); 15 //create Header 16 client.addHeader("apikey", "keyvalue");
GsonFormat安装方法:Android studio File->Settings..->Plugins–>Browse repositores..搜索GsonFormat。安装插件,重启android studio。GsonFormat插件主要是用于一键创建实体类的,创建一个类,在类的内部使用alt+Inset后,在弹出的对话框中将json数据粘贴到里边,json格式正确即可生成对应的类。界面操作如下图所示:
Gson 是 Google 提供的用来在 Java 对象和 JSON 数据之间进行映射的 Java 类库。可以将一个 JSON 字符串转成一个 Java 对象,或者反过来。更多关于GSON的API可以访问:http://sites.google.com/site/gson
基本使用如下:
1 //声明Gson对象 2 Gson gson=new Gson(); 3 //json字符串转换为对应类的对象 4 Person person = gson.fromJson(str, Person.class);
Android天气接口调用项目结构图如下所示:
接口地址: http://apis.baidu.com/heweather/weather/free。网页介绍地址:http://apistore.baidu.com/apiworks/servicedetail/478.html。点击网页调试界面如下所示:
天气获取是通过在MainActivity中刷新时,重新向网络发送请求获取数据。获取到天气数据后利用ContentProvider提供的共有模式保存数据,其中,由于返回格式的json数据格式利用GsonFormat插件生成类时会异常,主要是类的命名不规则,替换HeWeather data service 3.0字符串,改为一个规范的类名称即可。生成对应的Bean类以后,利用Gson的方式并可彻底解析Json字符串数据了。 天气数据请求及保存核心代码如下:
1 /* 2 利用异步网络请求:AsyncHttpClient 请求天气数据 3 */ 4 public void GetWeather() 5 { 6 try { 7 String select_city = "?city=" + citypinyin + ""; 8 HttpUtils.get(select_city, null, new TextHttpResponseHandler() { 9 @Override 10 public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) { 11 } 12 @Override 13 public void onSuccess(int statusCode, Header[] headers, String responseString) { 14 //返回字符串不规则,先替换一下 对于Json数据,做数据分割,对于双引号之间的内容分割,用split("\"") 15 String temp_old_replace= responseString.split("\"")[1]; 16 String temp_new_replace="HeWeatherDataService"; 17 responseString = responseString.replaceAll(temp_old_replace, temp_new_replace); 18 //获取到数据以后,做数据保存 19 ContentValues contentValues = new ContentValues(); 20 contentValues.put(DatabaseHelper.City_name, citypinyin); 21 contentValues.put(DatabaseHelper.City_Weather, responseString); 22 //先删除数据 23 int delete_result = weatherprovider.delete(weather_uri, null, null); 24 if (delete_result != -1) { 25 Uri insert_result = weatherprovider.insert(weather_uri, contentValues); 26 if (insert_result != null) { 27 //Toast.makeText(MainActivity.this, "数据本地保存成功", Toast.LENGTH_SHORT).show(); 28 } else { 29 Toast.makeText(MainActivity.this, "数据本地保存失败", Toast.LENGTH_SHORT).show(); 30 } 31 } else { 32 Toast.makeText(MainActivity.this, "本地数据清除失败", Toast.LENGTH_SHORT).show(); 33 } 34 } 35 }); 36 }catch (Exception ex) 37 { 38 } 39 }
ContentProvider中定义操作数据库的函数及Uri,详细代码如下:
1 package www.csnt.com.geekbandsevenhomework.provider; 2 3 import android.content.ContentProvider; 4 import android.content.ContentUris; 5 import android.content.ContentValues; 6 import android.content.UriMatcher; 7 import android.database.Cursor; 8 import android.database.sqlite.SQLiteDatabase; 9 import android.net.Uri; 10 import android.support.annotation.Nullable; 11 import android.text.TextUtils; 12 13 import www.csnt.com.geekbandsevenhomework.db.DatabaseHelper; 14 15 /** 16 * Function:Create ContentProvider for Weather table 17 * Create date on 16/4/7. 18 * 19 * @author wangling 20 * @version 1.0 21 */ 22 public class WeatherContentProvider extends ContentProvider { 23 private SQLiteDatabase mSqLiteDatabase; 24 private static UriMatcher sUriMatcher; 25 public static final int URI_MATCH_WEATHER = 1; 26 @Override 27 public boolean onCreate() { 28 DatabaseHelper databaseHelper = new DatabaseHelper(getContext()); 29 mSqLiteDatabase = databaseHelper.getWritableDatabase(); 30 sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 31 // content://www.csnt.com.geekbandsevenhomework/weather 1 32 sUriMatcher.addURI(URIList.AUTHORITY, DatabaseHelper.WEATHER_TABEL_NAME, URI_MATCH_WEATHER); 33 return false; 34 } 35 36 @Nullable 37 @Override 38 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 39 String tableName = getTableName(uri); 40 if(TextUtils.isEmpty(tableName)){ 41 return null; 42 } 43 Cursor cursor = mSqLiteDatabase 44 .query(tableName, projection,selection, selectionArgs,null, null, sortOrder); 45 return cursor; 46 } 47 48 @Nullable 49 @Override 50 public String getType(Uri uri) { 51 return null; 52 } 53 54 @Nullable 55 @Override 56 public Uri insert(Uri uri, ContentValues values) { 57 String tableName = getTableName(uri); 58 if(TextUtils.isEmpty(tableName)){ 59 return null; 60 } 61 long id = mSqLiteDatabase.insert(tableName, null,values); 62 return ContentUris.withAppendedId(uri, id); 63 } 64 65 @Override 66 public int delete(Uri uri, String selection, String[] selectionArgs) { 67 String tableName = getTableName(uri); 68 if(TextUtils.isEmpty(tableName)){ 69 return -1; 70 } 71 int count =mSqLiteDatabase.delete(tableName, selection,selectionArgs); 72 return count; 73 } 74 75 @Override 76 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 77 String tableName = getTableName(uri); 78 if(TextUtils.isEmpty(tableName)){ 79 return -1; 80 } 81 int count = mSqLiteDatabase.update(tableName, values,selection,selectionArgs); 82 return count; 83 } 84 85 private String getTableName(Uri uri){ 86 int type = sUriMatcher.match(uri); 87 String tableName = null; 88 switch (type){ 89 case URI_MATCH_WEATHER: //定义天气查询 90 tableName = DatabaseHelper.WEATHER_TABEL_NAME; 91 break; 92 } 93 return tableName; 94 95 } 96 }
本项目源代码在360云盘上,开发环境为 Android Studio 2.0 。
https://yunpan.cn/cYamkZG3sq9jf 访问密码 f3d5。文件名称:android天气查询demo。
原文:http://www.cnblogs.com/wlandwl/p/android_7.html