Android 使用Volley 解析JSON

时间:2020-02-23 14:29:01  来源:igfitidea点击:

在本教程中,我们将在Android中使用Volley 解析JSON。

之前,我们看到了Android JSON解析教程非常简单。

在本教程中,我们将使用外部库volle权来发送HTTP请求。
我们可以将其视为以前的教程中ASYNCTASK的替代品。

为什么要使用Volley而不是AsyncTask

  • 不太复杂
  • 高效的网络管理。
  • 轻松定制

例子 :

我已经实现了Restful WebServices JSON示例。

我将使用相同的例子来实现RESTful Web服务。
如果我们要部署以上Web服务,请使用以下URL来获取JSON数据

<span style="color: green; font-weight: bold;">http://192.168.2.22:8080/JAXRSJsonExample/rest/countries

192.168.2.22是我机器的IP地址。
在计算机上实现此Web服务后,我们应该用IP地址替换它。
如果我们不想自己实现REST Web服务并希望低于JSON响应。
我们可以使用以下链接。
https://cdn.rawgit.com/arpitmandliya/androidrestjsonexample/master/countries.json我们将从上面的URL上获得以下JSON响应:

[ 
 { 
 "id":1,
 "countryName":"San Franceco"
 },
 { 
 "id":4,
 "countryName":"China"
 },
 { 
 "id":3,
 "countryName":"Nepal"
 },
 { 
 "id":2,
 "countryName":"Bhutan"
 }
]

我们从REST Web服务中获得了JSONARRAY。
如果我们不熟悉JSON,则可以通过JSON教程进行。

我们将渲染以上JSON响应Android自定义列表查看:

第1步:创建项目

创建一个Android应用程序ProjectNamed"JSONPASINGUSINGVOLLEY"。

第2步:添加凌空地面依赖性

对于使用volley库,我们需要添加volley依赖关系"compile'com.mc.mcxiacoke.volley:1.0.19'"在build.gradle中(模块:应用程序)

apply plugin: 'com.android.application'
 
android {
    compileSdkVersion 25
    buildToolsVersion "25.0.0"
    defaultConfig {
        applicationId "com.theitroad.jsonparsingusingvolley"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
 
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.0.0'
    compile 'com.mcxiaoke.volley:library:1.0.19'
    testCompile 'junit:junit:4.12'
}

第3步:创建布局

更改RES - >布局 - > Activity_main.xml如下所示:

<?xml version="1.0" encoding="utf-8"?>
<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="10dp"
 tools:context="com.theitroad.androidrestjsonexample.MainActivity">
 
 <Button
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Fetching countries data"
 android:id="@+id/btnSubmit"
 
 
 <ListView
 android:id="@+id/android:list"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_below="@id/btnSubmit"
 
</RelativeLayout>

我们有一个按钮和ListView。
单击按钮时,我们将通过调用RESTful Web服务并在ListView上渲染它来填充ListView中的数据。

第4步:为行创建布局

正如我们在Activity_main.xml中声明listview小部件。
现在我们需要为单个行提供布局。

  • 转到res - >布局
  • 右键单击布局
  • 单击"新建 - >文件"。
  • 创建名为"row_item.xml"的文件,并在row_item.xml中粘贴以下代码。
<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent" >
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_columnWeight="1"
 android:layout_marginLeft="10dp"
 android:textSize="30dp"
 android:textColor="#1E90FF"
 android:id="@+id/textViewId"
 android:layout_row="0"
 android:layout_column="1" 
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_columnWeight="1"
 android:layout_marginLeft="10dp"
 android:textSize="20dp"
 android:textColor="#4B0082"
 android:id="@+id/textViewCountry"
 android:layout_row="1"
 android:layout_column="1" 
</GridLayout>

第5步:创建模型对象国家/地区:

如果我们注意到,我们从RESTful Web服务中获取JSON数组,其中有4项。
每个项目都有两个属性ID和CountryName。
我们将为每个项目创建国家对象。

package com.theitroad.androidrestjsonexample;
public class Country{
    int id;
    String countryName;
 
    public Country(int i, String countryName) {
        super();
        this.id = i;
        this.countryName = countryName;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getCountryName() {
        return countryName;
    }
    public void setCountryName(String countryName) {
        this.countryName = countryName;
    }
}

步骤6:为ListView创建BaseAdapter

在创建捕获期之前,我们需要为自定义ListView行创建CustomCountrylist类。

package com.theitroad.androidrestjsonexample;
 
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
 
import com.theitroad.androidrestjsonexample.Country;
import com.theitroad.androidrestjsonexample.R;
 
import java.util.ArrayList;
 
public class CustomCountryList extends BaseAdapter {
 
 
    private Activity context;
    ArrayList countries;
 
 
    public CustomCountryList(Activity context, ArrayList countries) {
     //  super(context, R.layout.row_item, countries);
        this.context = context;
        this.countries=countries;
 
    }
 
    public static class ViewHolder
    {
        TextView textViewId;
        TextView textViewCountry;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row=convertView;
 
        LayoutInflater inflater = context.getLayoutInflater();
        ViewHolder vh;
        if(convertView==null) {
            vh=new ViewHolder();
            row = inflater.inflate(R.layout.row_item, null, true);
            vh.textViewId = (TextView) row.findViewById(R.id.textViewId);
            vh.textViewCountry = (TextView) row.findViewById(R.id.textViewCountry);
            //store the holder with the view.
            row.setTag(vh);
        }
        else {
            vh = (ViewHolder) convertView.getTag();
        }
 
        vh.textViewCountry.setText(countries.get(position).getCountryName());
        vh.textViewId.setText(""+countries.get(position).getId());
 
        return  row;
    }
 
    public long getItemId(int position) {
        return position;
    }
 
    public Object getItem(int position) {
        return position;
    }
 
    public int getCount() {
 
        if(countries.size()<=0)
            return 1;
        return countries.size();
    }
}

此类用于填充ListView的数据。
GetView方法被调用以绘制每一行。

第7步:创建MainActivity

我们将使用jsonArrayrequest类的凌空库 。

JsonArrayRequest req = new JsonArrayRequest(jsonURl,
                    new Response.Listener() {
                        @Override
                        public void onResponse(JSONArray response) {... , new Response.ErrorListener() {
                            @Override
                            public void onErrorResponse(VolleyError error) {...)

它有三个参数。

  • 返回jsonArray响应的REST Web服务URL。
  • 传递具有呼叫响应的方法的侦听器在获取REST URL的响应时会被调用。
  • 通过errorListener,当我们在执行REST Web服务URL时出现任何错误时,将在发生任何错误时调用orerrorresponse。

我们还可以使用volley类使用jsonObjectRequest或者stringRequest取决于需求。

更改src/main/packageName/mainActivity.java如下:

package com.theitroad.jsonparsingusingvolley;
 
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.Volley;
 
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
 
import java.net.URL;
import java.util.ArrayList;
import static android.content.ContentValues.TAG;
 
public class MainActivity extends AppCompatActivity {
 
    private Button btnSubmit;
    String responseText;
    Activity activity;
    ArrayList countries=new ArrayList();
    private ProgressDialog progressDialog;
    ListView listView;
 
    //In case if you deploy rest web service, then use below link and replace below ip address with yours
    //http://192.168.2.22:8080/JAXRSJsonExample/rest/countries
    
    //Direct Web services URL
    private String path = "https://cdn.rawgit.com/arpitmandliya/AndroidRestJSONExample/master/countries.json";
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        activity = this;
        btnSubmit = (Button) findViewById(R.id.btnSubmit);
        listView = (ListView) findViewById(android.R.id.list);
        btnSubmit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                countries.clear();
 
                progressDialog = new ProgressDialog(MainActivity.this);
                progressDialog.setMessage("Fetching conntry data");
                progressDialog.setCancelable(false);
                progressDialog.show();
                //Call WebService
                getWebServiceResponseData();
            }
        });
    }
 
    protected Void getWebServiceResponseData() {
            JsonArrayRequest req = new JsonArrayRequest(jsonURl,
                    new Response.Listener() {
                        @Override
                        public void onResponse(JSONArray response) {
                            Log.d(TAG, response.toString());
                            if (progressDialog.isShowing())
                                progressDialog.dismiss();
 
                            //Parsing json response and iterate over each JSON object
                            Log.d(TAG, "data:" + responseText);
                            try {
 
                                for (int i = 0; i < response.length(); i++) {
                                    JSONObject jsonobject = response.getJSONObject(i);
                                    int id = jsonobject.getInt("id");
                                    String country = jsonobject.getString("countryName");
                                    Log.d(TAG, "id:" + id);
                                    Log.d(TAG, "country:" + country);
                                    Country countryObj = new Country(id, country);
                                    countries.add(countryObj);
                                }
                            } catch (JSONException e) {
                                e.printStackTrace();
                                Toast.makeText(getApplicationContext(),
                                        "Error: " + e.getMessage(),
                                        Toast.LENGTH_LONG).show();
                            }
 
                            CustomCountryList customCountryList = new CustomCountryList(activity, countries);
                            listView.setAdapter(customCountryList);
 
                            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                                @Override
                                public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                                    Toast.makeText(getApplicationContext(),"You Selected "+countries.get(position).getCountryName()+ " as Country",Toast.LENGTH_SHORT).show();        }
                            });
                         }
                        },   new Response.ErrorListener() {
                            @Override
                            public void onErrorResponse(VolleyError error) {
                                Toast.makeText(MainActivity.this,error.getMessage(),Toast.LENGTH_LONG).show();
                            }
 
                        });
                        RequestQueue requestQueue = Volley.newRequestQueue(this);
                        requestQueue.add(req);
            return null;
        }
    }

第8步:在androidmanifest.xml中添加Internet权限

复制以下代码:

<uses-permission android:name="android.permission.INTERNET" 

把它放在androidmanifest.xml中

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="com.theitroad.jsonparsingusingvolley">
 
 <uses-permission android:name="android.permission.INTERNET" 
 <application
 android:allowBackup="true"
 android:icon="@mipmap/ic_launcher"
 android:label="@string/app_name"
 android:supportsRtl="true"
 android:theme="@style/AppTheme">
 <activity android:name=".MainActivity">
 <intent-filter>
 <action android:name="android.intent.action.MAIN" 
 
 <category android:name="android.intent.category.LAUNCHER" 
 </intent-filter>
 </activity>
 </application>
 
</manifest>

完成了,我们为Androidmanifest.xml添加了Internet权限。