如何使用HTTP URL Connection方法调用服务
在本教程中,我们将使用 GET 方法调用一个服务,并将示例 JSON 数据填充到 RecyclerView 中,而无需使用任何外部库。
示例 JSON
这是一个非常简单的 JSON,它提供了《权力的游戏》的列表详情,其中每个节点包含一些信息,例如战争名称、地点、地区、进攻方国王和防守方国王。
JSON Sample:-
[
{
    "name": "Battle of the Golden Tooth",
    "attacker_king": "Joffrey/Tommen Baratheon",
    "defender_king": "Robb Stark",
    "location": "Golden Tooth",
    "region": "The Westerlands"
  },
  {
    "name": "Battle at the Mummer's Ford",
    "attacker_king": "Joffrey/Tommen Baratheon",
    "defender_king": "Robb Stark",
    "location": "Mummer's Ford",
    "region": "The Riverlands"
  }
]
您可以通过访问以下网址获取此 JSON 数据:
URL: https://blogurl-3f73f.firebaseapp.com/
我假设您对 JSON 格式有基本的了解。
创建新项目
在 Android Studio 中从文件 ⇒ 新项目创建新项目,填写所需详细信息。
由于我们需要进行网络请求,因此需要在 AndroidManifest.xml 中添加 INTERNET 权限。
<uses-permission android:name="android.permission.INTERNET" />
在 RecyclerView 中填充数据
要启用 RecyclerView 和 Card View 元素,您需要在 build.gradle 文件中添加依赖项:
dependencies {    
compile fileTree(dir: 'libs', include: ['*.jar']) 
compile 'com.android.support:appcompat-v7:25.1.0'  
testCompile 'junit:junit:4.12'
compile 'com.android.support:cardview-v7:25.0.1'
compile 'com.android.support:recyclerview-v7:25.0.1'
   }
在进行 http 调用之前,首先在我们的主 Activity 中添加一个按钮和一个 RecyclerView。打开主 Activity 的布局文件 (activity_main.xml),并添加一个 Button 和 RecyclerView 元素。
    <Button    
      android:id="@+id/btnCreateConnection"  
      android:layout_width="match_parent"   
      android:layout_height="wrap_content"  
      android:text="Create Connection"/>
 
    <android.support.v7.widget.RecyclerView  
      android:id="@+id/recyclerView"
      android:layout_width="match_parent"    
      android:layout_height="match_parent"/>
由于我们通过进行 HTTP 调用来获取 JSON,因此我添加了一个 Async 类 GetWarInfo,以便在后台线程中进行 http 调用。在您的主 Activity 类中添加以下方法。
在 doInBackground() 方法中,调用 HTTP_URL_CONNECTION_GET() 从 URL 获取 json。一旦获取到 json,就会对其进行解析,并将每个联系人添加到数组列表中。
请注意,我根据节点的类型使用了 getJSONArray() 或 getJSONObject() 方法。
package com.bytemachine.urlconnectionwithrecyclerview;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
    // declaring variables
    Button btnCreateConnection;
    RecyclerView recyclerView;
    List<ModelWarDetails> listWarDetails=new ArrayList<>();
    RecyclerViewAdapter adapter;
    LinearLayoutManager llm;
    //onCreate calls when the application loads for the first time.
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView= (RecyclerView) findViewById(R.id.recyclerView);
        llm=new LinearLayoutManager(this);
        recyclerView.setLayoutManager(llm);
        btnCreateConnection= (Button) findViewById(R.id.btnCreateConnection);
        //setting click event on Button
        btnCreateConnection.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //executing Async task class to create HTTP connection
                new FetchWarsInfo().execute();
            }
        });
    }
    /**
     * Async task class to get json response by making HTTP call
     * Async task class is used because 
     * you cannot create a network connection on main thread
     */
    public class FetchWarsInfo extends AsyncTask<Void, Void, Void> {
        ProgressDialog progressDialog;
        static final String URL_STRING = 
        "https://blogurl-3f73f.firebaseapp.com/";
        String response;
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            progressDialog = new ProgressDialog(MainActivity.this);
            progressDialog.setCancelable(false);
            progressDialog.setMessage("Please wait. Fetching data..");
            progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            progressDialog.setProgress(0);
            progressDialog.show();
         }
        @Override
        protected Void doInBackground(Void... voids) {
            /*
            creatingURLConnection is a function use to establish connection
            */
            response = creatingURLConnection(URL_STRING);
            return null;
        }
        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            progressDialog.dismiss();
            Toast.makeText(getApplicationContext(),
            "Connection successful.",Toast.LENGTH_SHORT).show();
            try{
                if(response!=null && !response.equals("")){
                    /*
                    converting JSON response string into JSONArray
                    */
                    JSONArray responseArray = new JSONArray(response);
                    if(responseArray.length()>0){
                        /*
                        Iterating JSON object from JSON Array one by one
                        */
                        for(int i=0;i<responseArray.length();i++){
                            JSONObject battleObj = responseArray.getJSONObject(i);
                            //creating object of model class(ModelWarDetails)
                            ModelWarDetails modelWarDetails = new ModelWarDetails();
                            /*
                            fetching data based on key from JSON and setting into model class
                            */
                            modelWarDetails.setName(battleObj.optString("name"));
                            modelWarDetails.setAttacker_king
                            (battleObj.optString("attacker_king"));
                            modelWarDetails.setDefender_king
                            (battleObj.optString("defender_king"));
                            modelWarDetails.setLocation(battleObj.optString("location"));
                            //adding data into List
                            listWarDetails.add(modelWarDetails);
                        }
                        //calling RecyclerViewAdapter constructor by passing context and list
                        adapter = new RecyclerViewAdapter(getApplicationContext(),listWarDetails);
                        //setting adapter on recyclerView
                        recyclerView.setAdapter(adapter);
                        // to notify adapter about changes in list data(if changes)
                        adapter.notifyDataSetChanged();
                    }
                }else {
                    Toast.makeText(getApplicationContext(),
                                   "Error in fetching data.",Toast.LENGTH_SHORT).show();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    public String creatingURLConnection (String GET_URL) {
        String response = "";
        HttpURLConnection conn ;
        StringBuilder jsonResults = new StringBuilder();
        try {
            //setting URL to connect with
            URL url = new URL(GET_URL);
            //creating connection
            conn = (HttpURLConnection) url.openConnection();
            /*
            converting response into String
            */
            InputStreamReader in = new InputStreamReader(conn.getInputStream());
            int read;
            char[] buff = new char[1024];
            while ((read = in.read(buff)) != -1) {
                jsonResults.append(buff, 0, read);
            }
            response = jsonResults.toString();
        }catch(Exception e){
            e.printStackTrace();
        }
        return response;
    }
}
创建另一个名为 list_war_details.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"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:elevation="4dp"
        android:layout_margin="8dp"
        app:cardCornerRadius="4dp"
        app:cardBackgroundColor="#FFFFFF"
        android:id="@+id/layoutCard">
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <LinearLayout
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
                <LinearLayout
                    android:orientation="vertical"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:padding="16dp">
                    <ImageView
                        android:layout_width="36dp"
                        android:layout_height="36dp"
                        android:id="@+id/imageView2"
                        android:src="@drawable/image_crown1"/>
                </LinearLayout>
                <LinearLayout
                    android:orientation="vertical"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:paddingLeft="8dp"
                    android:paddingRight="8dp"
                    android:paddingBottom="8dp"
                    android:paddingTop="8dp">
                    <TextView
                        android:text="TextView"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:id="@+id/txtName"
                        android:paddingTop="4dp"
                        android:paddingBottom="4dp"
                        android:textSize="18sp"
                        android:textColor="#000000" />
                    <TextView
                        android:text="TextView"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:id="@+id/txtLocation"
                        android:paddingBottom="4dp"
                        android:textSize="12sp" />
                </LinearLayout>
            </LinearLayout>
            <View
                android:layout_width="match_parent"
                android:layout_height="0.1dp"
                android:background="#d1d1d1"></View>
            <LinearLayout
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingLeft="16dp"
                android:paddingRight="16dp"
                android:paddingTop="8dp"
                android:paddingBottom="8dp">
                <TextView
                    android:text="Attacker King"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/txtAttackerKing"
                    android:layout_weight="1"
                    android:paddingTop="4dp"
                    android:paddingBottom="4dp" />
                <TextView
                    android:text="Defender King"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:id="@+id/txtDefenderKing"
                    android:layout_weight="1"
                    android:gravity="right"
                    android:paddingBottom="4dp"
                    android:paddingTop="4dp" />
            </LinearLayout>
        </LinearLayout>
    </android.support.v7.widget.CardView>
</LinearLayout>
在添加 RecyclerView 部件后,让我们开始编写 adapter 类来渲染数据。
为此,您需要创建一个名为 ModelWarDetails.java 的模型类,并声明 name、location、attacker_king、defender_king。 此外,为每个变量添加 getter/setter 方法。
创建一个 DAO(数据访问对象),通常称为 Modal 类,名为 ModelWarDetails.java。 声明变量(name、location、attacker_king 和 defender_king),并生成 getter 和 setter。
:您可以通过按 alt + insert 生成 getter 和 setter。
package com.bytemachine.urlconnectionwithrecyclerview;
class ModelWarDetails {
    private String name;
    private String location;
    private String attacker_king;
    private String defender_king;
    private String defender_king1;
    String getName() {
        return name;
    }
    void setName(String name) {
        this.name = name;
    }
     String getLocation() {
        return location;
    }
    void setLocation(String location) {
        this.location = location;
    }
    String getAttacker_king() {
        return attacker_king;
    }
    void setAttacker_king(String attacker_king) {
        this.attacker_king = attacker_king;
    }
    String getDefender_king() {
        return defender_king;
    }
    void setDefender_king(String defender_king) {
        this.defender_king = defender_king;
    }
}
现在创建一个名为 RecyclerViewAdapter.java 的类,并添加以下代码。 在这里,onCreateViewHolder() 方法会加载 list_war_details.xml。 在 onBindViewHolder() 方法中,将适当的战争数据(name、location、attacker_king 和 defender_king)设置为每一行。
getItemCount() 方法给出列表的大小。
package com.bytemachine.urlconnectionwithrecyclerview;
import android.content.Context;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
 class RecyclerViewAdapter extends 
 RecyclerView.Adapter<RecyclerViewAdapter.ViewHolderWarDetails> {
     // declaring variables
     private Context context;
     private List<ModelWarDetails> listWarDetails;
     //constructor
     RecyclerViewAdapter(Context context, List<ModelWarDetails> listWarDetails) {
        this.context = context;
        this.listWarDetails = listWarDetails;
    }
    @Override
    public ViewHolderWarDetails onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.list_war_details,parent,false);
        ViewHolderWarDetails viewHolderWarDetails = new ViewHolderWarDetails(view);
        return viewHolderWarDetails;
    }
    @Override
    public void onBindViewHolder(ViewHolderWarDetails holder, int position) {
        //setting data on each row of list according to position.
        holder.txtName.setText(listWarDetails.get(position).getName());
        holder.txtLocation.setText(listWarDetails.get(position).getLocation());
        holder.txtAttackerKing.setText(listWarDetails.get(position).getAttacker_king());
        holder.txtDefenderKing.setText(listWarDetails.get(position).getDefender_king());
    }
     //returns list size
    @Override
    public int getItemCount() {
        return listWarDetails.size();
    }
     class ViewHolderWarDetails extends RecyclerView.ViewHolder{
         // declaring variables
         TextView txtName, txtLocation, txtAttackerKing,txtDefenderKing;
         CardView layoutCard;
         ViewHolderWarDetails(View v) {
            super(v);
            txtName = (TextView) v.findViewById(R.id.txtName);
            txtLocation = (TextView) v.findViewById(R.id.txtLocation);
            txtAttackerKing = (TextView) v.findViewById(R.id.txtAttackerKing);
            txtDefenderKing = (TextView) v.findViewById(R.id.txtDefenderKing);
            layoutCard = (CardView) v.findViewById(R.id.layoutCard);
        }
    }
}
现在,如果您运行该应用程序,您将看到战争详情以列表方式显示。

请随时通过 bytemachines.inc@gmail.com 与我联系。
祝您编码愉快!



