使用okHttp讀取JSON資料並用RxJava框架解析JSON格式資料成Gson
介紹
什麼是JSON?,JSON的全名是JavaScript Object Notation,用途是資料交換。之前會使用XML來做資料交換,可是當資料量很多時,XML檔會變很肥大,而JSON是輕量級的資料交換格式。物件是以左大括號 { 開始,右大括號 } 結束。並以key:value的方式來儲存資料,多組的話則以逗號分開,看起來如下
{
"Data": [
{
"Id": "0f4e3749-fdfa-42a3-9023-752e478297db",
"Name": "雷霆專案"
},
{
"Id": "be92c897-56fa-43b6-9d5b-12aebdc5bbce",
"Name": "蜂眼專案"
}
]
}
Gson是google開發用來解析JSON格式資料的Library,主要為方便將Java物件序列化至輕量化的JSON格式,或從JSON反序列化至JAVA物件。
OkHttp是一個網路的應用程式框架,可快速實作資料交換的動作,讓Http連線的過程更有效率。使用OkHttp,可以簡化需先設計AsyncTask、輸出入迴圈或是許多執行緒等工作,讓開發的速度加快。官方網址
RxJava最主要的兩個是Observables和Subscribers。Observables會發出事件,而Subscribers處理這一些事件。一個Observable可以發出零個或多個事件,直到結束或出錯。每發出一個事件,就會使用他的subscriber的onNext方法,最後使用subscriber.onCompleted()或subscriber.onError()結束。 有一點要注意的是,如果Observerble沒有Subscriber,那這個Observerble就不會發出事件。 RxJava有一個很棒的優點,假設你要照順序的做處理,用RxJava可輕鬆的完成同步。
gradle設置
加入OkHttp、Gson和RxJava。
compile 'com.squareup.okhttp3:okhttp:3.4.1'
compile 'com.google.code.gson:gson:2.3.1'
compile 'io.reactivex:rxandroid:1.2.1'
設置NumberPicker
先設定NumberPicker,將字串加入到NumberPicker,之後要將取得的資料,以NumberPicker的方式呈現。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.royshow.gsontest.MainActivity">
<NumberPicker
android:id="@+id/showNumProjectPicker"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="60dp"
android:layout_marginTop="40dp" >
</NumberPicker>
</RelativeLayout>
先將NumberPicker放入字串,並初始值。
public class MainActivity extends AppCompatActivity {
private NumberPicker showNumProjectPicker;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] items = {"test1", "test2", "test3", "test4"};
showNumProjectPicker = (NumberPicker) findViewById(R.id.showNumProjectPicker);
showNumProjectPicker.setMinValue(0);
showNumProjectPicker.setMaxValue(items.length - 1);
showNumProjectPicker.setDisplayedValues(items);
showNumProjectPicker.setWrapSelectorWheel(false);
showNumProjectPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
}
}
OkHttp讀取JSON
在最外面宣告OkHttpClient。
private OkHttpClient client = new OkHttpClient();
然後在OnCreate裡面實作,如下,執行後會發現,是以非同步的方式執行的,再之後要將資料放進NumberPicker,會是一個問題,這裡先不用管,之後會利用RxJava來解決。
Request request = new Request.Builder().url("你的JSON Url").build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String json = response.body().string();
Log.d("OkHttp", json);
}
});
可以讀取到JSON的資料,如下圖
定義JAVA格式的Data
新增Project.java、ProjectResponse.java和ProjectViewModel.java,定義需要儲存的格式。
Project.java
public class Project {
public Project() {
}
@SerializedName("Id")
private String id;
@SerializedName("Name")
private String name;
@SerializedName("Code")
private String code;
@SerializedName("Description")
private String description;
public String getId() {
return id;
}
public Project setId(String id) {
this.id = id;
return this;
}
public String getName() {
return name;
}
public Project setName(String name) {
this.name = name;
return this;
}
public String getCode() {
return code;
}
public Project setCode(String code) {
this.code = code;
return this;
}
public String getDescription() {
return description;
}
public Project setDescription(String description) {
this.description = description;
return this;
}
}
ProjectResponse.java
public class ProjectResponse {
@SerializedName("Data")
private List<Project> projects;
public List<Project> getProjects() {
return projects;
}
}
ProjectViewModel.java
public class ProjectViewModel {
private List<Project> projects;
public ProjectViewModel(List<Project> projects) {
this.projects = projects;
}
public List<Project> getProjects() {
return projects;
}
}
RxJava框架解析JSON格式資料成Gson
現在要將之前解析Json的Code,放到RxJava的方法裡,在這裡新增一個function,將RxJava的方法寫在這裡面,將Json格式解析成Java格式。為了達到同步的效果,才能讓資料先解析後,再放到NumberPicker顯示,使用了RxJava的subscribeOn建立一個新的Thread,以及observeOn保證一定會同步。
public void init() {
Observable.create(new Observable.OnSubscribe<ProjectViewModel>() {
@Override
public void call(Subscriber<? super ProjectViewModel> subscriber) {
try {
Request request = new Request.Builder().url("你的JSON Url").build();
Response projectResponse = client.newCall(request).execute();
ProjectResponse tmpProjectResponse = new Gson().fromJson(projectResponse.body().string(), ProjectResponse.class);
subscriber.onNext(new ProjectViewModel(tmpProjectResponse.getProjects()));
subscriber.onCompleted();
} catch (Exception e) {
subscriber.onError(e);
}
}
})
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<ProjectViewModel>() {
@Override
public void call(ProjectViewModel projectViewModel) {
String[] items = new String[projectViewModel.getProjects().size()];
for (int i = 0; i < items.length; i++) {
items[i] = projectViewModel.getProjects().get(i).getName();
}
showNumProjectPicker.setMinValue(0);
showNumProjectPicker.setMaxValue(projectViewModel.getProjects().size() - 1);
showNumProjectPicker.setDisplayedValues(items);
showNumProjectPicker.setWrapSelectorWheel(false);
showNumProjectPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
Log.d("call", "call: " + throwable.getLocalizedMessage());
}
});
}