如何使用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 与我联系。
祝您编码愉快!