上一次我們透過Volley來取得臺北捷運列車到站資訊,此公開資料是每30秒就更新,我們要如何讓它更新呢?
在許多App上,使用者只須要到頁面的頂端,由上往下滑動,即可進行資料更新的動作,今天我們就來記錄一下,該如何做到這樣的效果。
完成圖↓
透過官方的SwipeRefreshLayout可以很輕鬆地做到這樣的功能,使用上一次的專案,將SwipeRefreshLayout加到「fragmentlist_one.xml」。
fragmentlist_one.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:background="@color/white" | |
android:gravity="center" | |
android:orientation="horizontal"> | |
<ProgressBar | |
android:id="@+id/progressBar" | |
style="?android:attr/progressBarStyle" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_gravity="center_vertical" /> | |
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
android:id="@+id/swipeRefreshLayout" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:visibility="gone"> | |
<android.support.v7.widget.RecyclerView | |
android:id="@+id/recyclerView" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:clipToPadding="false" /> | |
</android.support.v4.widget.SwipeRefreshLayout> | |
</LinearLayout> |
FragmentList_One.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.solinari.VerticalSwipeRefresh; | |
import android.os.Bundle; | |
import android.support.v4.app.Fragment; | |
import android.support.v4.widget.SwipeRefreshLayout; | |
import android.support.v7.widget.LinearLayoutManager; | |
import android.support.v7.widget.RecyclerView; | |
import android.view.LayoutInflater; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import android.widget.ProgressBar; | |
import android.widget.Toast; | |
import com.android.volley.Request; | |
import com.android.volley.RequestQueue; | |
import com.android.volley.Response; | |
import com.android.volley.VolleyError; | |
import com.android.volley.toolbox.JsonObjectRequest; | |
import com.android.volley.toolbox.Volley; | |
import org.json.JSONArray; | |
import org.json.JSONException; | |
import org.json.JSONObject; | |
/** | |
* Created by Solinari on 2016/12/31. | |
*/ | |
public class FragmentList_One extends Fragment{ | |
private RecyclerView recyclerView; | |
private SwipeRefreshLayout swipeRefreshLayout; | |
private ProgressBar progressBar; | |
private RecyclerView.Adapter recyclerAdapter; | |
private String[] MetroInfo; | |
public View onCreateView(LayoutInflater inflater, ViewGroup container, | |
Bundle savedInstanceState) { | |
View view = inflater.inflate(R.layout.fragmentlist_one, container, false); | |
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView); | |
progressBar = (ProgressBar) view.findViewById(R.id.progressBar); | |
swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeRefreshLayout); | |
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {//設置監聽器 | |
@Override | |
public void onRefresh() {//當使用者於頂端垂直滑動手勢時 | |
getMetroInfo();//取得台北捷運列車到站資訊 | |
recyclerAdapter.notifyDataSetChanged();//更新RecyclerView | |
swipeRefreshLayout.setRefreshing(false);//移除SwipeRefreshLayout更新時的loading圖示 | |
} | |
}); | |
getMetroInfo();//取得台北捷運列車到站資訊 | |
return view; | |
} | |
public void setRecyclerView(){ | |
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); | |
recyclerAdapter = new RecyclerViewAdapter(MetroInfo);//設置RecyclerView.Adapter | |
recyclerView.setAdapter(recyclerAdapter); | |
progressBar.setVisibility(View.GONE);//Loading圖隱藏 | |
swipeRefreshLayout.setVisibility(View.VISIBLE);//資料呈現 | |
} | |
public void getMetroInfo(){ | |
RequestQueue queue = Volley.newRequestQueue(getActivity());//創建一個RequestQueue | |
//台北捷運到站資料網址,按終點站排序 | |
String url = "http://data.taipei/opendata/datalist/apiAccess?scope=resourceAquire&rid=55ec6d6e-dc5c-4268-a725-d04cc262172b&sort=Destination"; | |
//對URL發出Request取得JsonObject的Response | |
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null, | |
new Response.Listener<JSONObject>() { | |
@Override | |
public void onResponse(JSONObject response) { | |
try { | |
//Response的JSONObject中,我們要的資訊是results(JSONArray) | |
//{"result":{"offset":0,"limit":10000,"count":25,"sort":"Destination","results":[{"_id":"1","Station":"士林站","Destination":"大安站","UpdateTime":"2017-04-10T20:59:27.577"},...}]}} | |
JSONArray info = response.getJSONObject("result").getJSONArray("results"); | |
MetroInfo = new String[info.length()]; | |
for(int i = 0; i < info.length();i++){ | |
JSONObject jsonObject = info.getJSONObject(i); | |
//{"_id":"1","Station":"士林站","Destination":"大安站","UpdateTime":"2017-04-10T20:59:27.577"} | |
String time = jsonObject.getString("UpdateTime").substring(11,19); | |
MetroInfo[i] = jsonObject.getString("Station") + "_" + jsonObject.getString("Destination") + "_" + time; | |
} | |
setRecyclerView();//設置RecyclerView | |
} catch (JSONException e) { | |
e.printStackTrace(); | |
} | |
} | |
}, new Response.ErrorListener() { | |
@Override | |
public void onErrorResponse(VolleyError error) { | |
//當發生錯誤時,提示使用者發生錯誤 | |
MetroInfo = new String[1]; | |
MetroInfo[0] = "Error_Error_Error"; | |
setRecyclerView(); | |
Toast.makeText(getActivity(),"Get data error !",Toast.LENGTH_LONG).show(); | |
} | |
} | |
); | |
//將Request加入RequestQueue | |
queue.add(jsonObjectRequest); | |
} | |
} |
Adding Swipe-to-Refresh To Your App
Responding to a Refresh Request
完整專案:Solinari GitHub