1. 程式人生 > >Android 整合okhttp3、listview解析json資料

Android 整合okhttp3、listview解析json資料

上上篇文章寫了個Android的模擬介面,終於派上用場了

現在我們將接口裡面的json資料通過ListView顯示出來,效果如下:

先講一下ListView吧, 講ListView之前,肯定要講Adapter,在Android應用程式中,採用資料和顯示分開實現的資料處理方式,由於資料來源形式多樣,例如ListView所展示的資料格式是有一定要求的,為匹配這個變換,,中間加了介面卡。資料介面卡正是建立了資料來源與ListView之間的適配關係,將資料來源轉換為ListView能夠顯示的資料格式,從而將資料的來源 與資料的顯示進行 解耦,降低程式的耦合度。我這次用的是最常用的BaseAdapter,直接放程式碼,註釋都在程式碼裡。

public class MyAdapter extends BaseAdapter {
    private LinkedList<ClientInfo> mData;//ClientInfo為資料來源的內容格式
    private Context context;//佈局裝載器物件

    public MyAdapter(LinkedList<ClientInfo> mData, Context context) {
        this.mData = mData;
        this.context = context;
    }

    //要繫結的條目的數目
    @Override
    public int getCount() {
        return mData.size();
    }

    //根據一個索引(位置)獲取該位置的物件
    @Override
    public Object getItem(int position) {
        return mData.get(position);
    }

    //獲取條目的id
    @Override
    public long getItemId(int position) {
        return position;
    }

    //獲取該條目要顯示的介面
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;
        //如果view未被例項化過,快取池中沒有對應的快取
        if (convertView==null){
            viewHolder = new ViewHolder();
            convertView = LayoutInflater.from(context).inflate(R.layout.item_list_client,parent,false);
            viewHolder.userName = (TextView) convertView.findViewById(R.id.username);
            viewHolder.name1 = (TextView) convertView.findViewById(R.id.name);
            viewHolder.phone = (TextView) convertView.findViewById(R.id.phone);
            viewHolder.address = (TextView) convertView.findViewById(R.id.address);
            //用setTag將convertView和viewHolder關聯
            convertView.setTag(viewHolder);
        }else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        //取出bean物件
        ClientInfo clientInfo = mData.get(position);
        //設定控制元件的資料
        viewHolder.userName.setText(clientInfo.getUserName());
        viewHolder.name1.setText(clientInfo.getName());
        viewHolder.phone.setText(clientInfo.getPhone());
        viewHolder.address.setText(clientInfo.getAddress());
        return convertView;

    }
    //ViewHolder用於快取控制元件,
    class ViewHolder{
        public TextView userName;
        public TextView name1;
        public TextView phone;
        public TextView address;
    }
}

 獲取介面中的資料,肯定是需要先 定義一個實體類的,我這裡就不全放程式碼了主要就是定義了幾個變數,建構函式還有一堆set、get方法,變數名貼一下。

public class ClientInfo {
    private String userName;
    private String name;
    private String phone;
    private String address;
}

接下來是重頭戲,okhttp3,看這裡

public class Okhttp2Activity extends AppCompatActivity {
    private Context mContext;
    private List<ClientInfo> mData=null;
    private MyAdapter myAdapter = null;
    private ListView listView;
    private Button btn;
    private final String url="http://192.168.43.210:8081/getJson";
    private OkHttpClient client;
    private JSONObject jsonObject1,jsonObject2;
    private JSONArray jsonArray;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_okhttp2);
        mContext = Okhttp2Activity.this;
        listView = (ListView) findViewById(R.id.list_client);
        btn = (Button) findViewById(R.id.btn);
        client = new OkHttpClient();
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Request request = new Request.Builder()
                        .url(url)
                        .cacheControl(CacheControl.FORCE_NETWORK)
                        .build();

                //非同步請求
                client.newCall(request).enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        Toast.makeText(Okhttp2Activity.this,e.getMessage(),Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        final String responseString = response.body().string();
                        //在主執行緒中修改UI
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    jsonObject1 = new JSONObject(responseString);
                                    jsonArray = jsonObject1.optJSONArray("data");
                                    mData = new LinkedList<ClientInfo>();                                 
                                    for(int i = 0;i<jsonArray.length();i++){
                                        jsonObject2 = jsonArray.optJSONObject(i);
                                            String username = jsonObject2.getString("client_username");
                                            String name1 = jsonObject2.getString("client_name");
                                            String phone = jsonObject2.getString("client_phone");
                                            String address = jsonObject2.getString("client_address");
                                            ClientInfo clientInfo = new ClientInfo(username,name1,phone,address);
                                            mData.add(clientInfo);
                                    }                                   
                                    myAdapter = new MyAdapter((LinkedList<ClientInfo>) mData,mContext);
                                    listView.setAdapter(myAdapter);

                                } catch (JSONException e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                    }
                });
            }
        });

    }
}

資料格式在我的上上篇部落格中有,可以去看一下。

對於ListView其實只需要進行這幾步

(1)在佈局中放置ListView控制元件

(2)準備ListView顯示的資料,我們這裡是 LinkedList<ClientInfo>

(3)獲取佈局的ListView控制元件

         listView = (ListView) findViewById(R.id.list_client);

(4)定義並初始化一個介面卡

         myAdapter = new MyAdapter((LinkedList<ClientInfo>) mData,mContext);

(5)將前面定義的介面卡,利用ListView的函式setAdapter()設定

         listView.setAdapter(myAdapter);

然後講一下OkHttp的具體使用方法

(1)首先建立一個OkHttpClient的例項,程式碼如下

         OkHttpClient client = new OkHttpClient();

(2)建立一個request物件,設定好目標地址,這裡發起的是get請求

         private final String url="http://192.168.43.210:8081/getJson";

         Request request = new Request.Builder() .url(url) .cacheControl(CacheControl.FORCE_NETWORK) .build();

(3)呼叫OkHttpClient的newCall()方法,建立Call物件,並呼叫它的exqueue()方法(非同步請求),建立一個Callback實             例,重寫他的兩個方法。

         其中,response物件就是伺服器返回的資料,獲取返回的json資料

        final String responseString = response.body().string();

然後就是解析json格式的資料,並放入介面卡繫結的LinkedList<ClientInfo>當中。

當然不要忘了在manifest裡面新增網路許可權<uses-permission android:name="android.permission.INTERNET" />

還有okttp3的架包

dependencies 

{ 
    ... 
    compile 'com.squareup.okhttp3:okhttp:3.2.0' compile 'com.squareup.okio:okio:1.7.0' 
    ...
}

最後貼一下兩個簡單的xml檔案

(1)item_list_client.xml

<?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:orientation="horizontal">
    <TextView
        android:id="@+id/username"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"/>
    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"/>
    <TextView
        android:id="@+id/phone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"/>
    <TextView
        android:id="@+id/address"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"/>
</LinearLayout>

(2)activity_okhttp2.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.administrator.myapplication.Okhttp2Activity"
    android:orientation="vertical">
    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="查詢" />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:id="@+id/username1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="使用者名稱"/>
        <TextView
            android:id="@+id/name1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="姓名"/>
        <TextView
            android:id="@+id/phone1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="手機號碼"/>
        <TextView
            android:id="@+id/address1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="地址"/>
    </LinearLayout>
    <ListView
        android:id="@+id/list_client"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    </ListView>
</LinearLayout>