Implement the function of loading product data over the network:
1. Declare network permissions in AndroidManifest.xml;
2. Add necessary third-party libraries such as okhttp, glide, gson, etc. to app/build.gradle;
3. Connect to the given Web service through OkHttpClient in MainActivity to obtain product data; the corresponding json data is a local json file named goods_list_data.json; the data content is: [
{“id”:1,”count”:”54,000″,”goodsName”:”Fuji Polaroid Camera”,”goodsPic”:”/img/polaroid.png”},
{“id”:2,”count”:”53,000″,”goodsName”:”Ganz Microwave Oven”,”goodsPic”:”/img/microwave_oven.png”},
{“id”:3,”count”:”14,000″,”goodsName”:”New National Standard Electric Vehicle”,”goodsPic”:”/img/electric_vehicle.png”},
{“id”:4,”count”:”16,000″,”goodsName”:”Official customized projector”,”goodsPic”:”/img/projector.png”},
{“id”:5,”count”:”04,000″,”goodsName”:”Midea 35L Oven”,”goodsPic”:”/img/oven.png”},
{“id”:6,”count”:”33,000″,”goodsName”:”Children’s Learning Table”,”goodsPic”:”/img/learning_table.png”}
]
The corresponding image is also stored in the local img file
4. Use the gson library to parse the product data in JSON format and convert it into a list of java bean product data objects (Goods class);
5. Create a MsgHandler class for asynchronously updating the product list;
6. Load and display network images through the glide control in GoodsAdapter.
1. Deploy network image resources
First, we need to deploy the corresponding files in a simple server (Tomcat). The directory structure of the data stored in the server is as shown below
E:. ├─goods │ └─img │ └─goods_list_data.json └─WEB-INF
Among them, the ROOT directory is under "apache-tomcat-9.0.65-windows-x64\webapps\ROOT"
, which represents the root directory of the Tomcat server.
- The goods folder stores the data used in the product list
- The goods\img folder stores the picture resources of the products.
- The
goods_list_data.json
file stores the data of the product list, as shown below.
[ {<!-- -->"id":1,"count":"54,000","goodsName":"Fuji Polaroid Camera","goodsPic":"/img/polaroid.png"}, {<!-- -->"id":2,"count":"53,000","goodsName":"Ganz Microwave Oven","goodsPic":"/img/microwave_oven.png"}, {<!-- -->"id":3,"count":"14,000","goodsName":"New National Standard Electric Vehicle","goodsPic":"/img/electric_vehicle.png"}, {<!-- -->"id":4,"count":"16,000","goodsName":"Official customized projector","goodsPic":"/img/projector.png"}, {<!-- -->"id":5,"count":"04,000","goodsName":"Midea 35L Oven","goodsPic":"/img/oven.png"}, {<!-- -->"id":6,"count":"33,000","goodsName":"Children's Learning Table","goodsPic":"/img/learning_table.png"} ]
After starting tomcat, you can visit http://localhost:8080/goods/goods_list_data.json
to display the information
2. Create project
- Open Android Studio and create a new Android project.
- Name the project and select the appropriate target API level and device type.
- Create a new Empty Activity.
3. Declare network permissions in AndroidManifest.xml
Add the following permission declaration in the AndroidManifest.xml file so that the app can access the network:
<uses-permission android:name="android.permission.INTERNET" />
A problem caused by network security policy that does not allow communication with localhost in clear text (non-encrypted) . This usually involves network security configuration, especially with the introduction of stricter network security policies in Android 9.0 (API level 28) and higher; therefore we also need to Configure network security profiles
One way to solve this problem is to use the HTTPS protocol instead of HTTP, since HTTPS is encrypted.
If you are testing your app locally, you can use Android's Network Security Profile
to allow clear text communication.
- Create a network security configuration file named
network_security_config.xml
in theres/xml
folder. If the folder does not exist, create it manually.
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true"> <trust-anchors> <certificates src="system" /> <certificates src="user" /> </trust-anchors> </base-config> </network-security-config>
- In the
AndroidManifest.xml
file, apply this network security profile to your app. Add theandroid:networkSecurityConfig
attribute inside the
element as follows:
<application android:networkSecurityConfig="@xml/network_security_config" <!-- Other attributes and elements --> > <!-- Other elements --> </application>
This will allow your app to communicate in the clear with localhost during local development and testing. Note, however, that in a production environment, HTTPS is highly recommended to ensure secure transmission of data.
If you are using an emulator or a real device, make sure to rebuild and deploy the app for the configuration to take effect. Also, if your server is running locally, make sure the server port and address are correct.
4. Add dependent libraries
Add OkHttp, Glide, and Gson dependency libraries to the app/build.gradle
file.
implementation("com.squareup.okhttp3:okhttp:4.9.1") implementation("com.squareup.okhttp3:logging-interceptor:4.9.1") implementation("com.google.code.gson:gson:2.8.8") implementation("com.github.bumptech.glide:glide:4.12.0") annotationProcessor("com.github.bumptech.glide:compiler:4.12.0")
Sync
Waiting for dependencies to be installed…
5. Create an XML layout file
Create a layout file, such as activity_main.xml
, in the res/layout
folder to display product data.
<?xml version="1.0" encoding="utf-8"?> <androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@ + id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"/>
Create an XML layout file to display product items
Create a layout file, such as item_goods.xml
, in the res/layout
folder to display each product item.
<?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="wrap_content" android:orientation="vertical" android:padding="16dp"> <ImageView android:id="@ + id/goodsImageView" android:layout_width="100dp" android:layout_height="100dp" android:scaleType="centerCrop" /> <TextView android:id="@ + id/goodsNameTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" /> </LinearLayout>
6. Create a Java Bean class
Create a Goods
class to represent product data.
public class Goods {<!-- --> private int id; private String count; private String goodsName; private String goodsPic; // Getters and setters }
7. Create an adapter class
Create a custom adapter class GoodsAdapter
to bind product data to RecyclerView.
public class GoodsAdapter extends RecyclerView.Adapter<GoodsAdapter.ViewHolder> {<!-- --> private List<Goods> goodsList; private Context context; public GoodsAdapter(Context context, List<Goods> goodsList) {<!-- --> this.context = context; this.goodsList = goodsList; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {<!-- --> View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_goods, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder, int position) {<!-- --> Goods goods = goodsList.get(position); holder.goodsNameTextView.setText(goods.getGoodsName()); // Load and display image using Glide Glide.with(context) .load(goods.getGoodsPic()) .into(holder.goodsImageView); } @Override public int getItemCount() {<!-- --> if (goodsList != null) {<!-- --> return goodsList.size(); } else {<!-- --> return 0; // Returning 0 means there is no data } } static class ViewHolder extends RecyclerView.ViewHolder {<!-- --> TextView goodsNameTextView; ImageView goodsImageView; ViewHolder(View itemView) {<!-- --> super(itemView); goodsNameTextView = itemView.findViewById(R.id.goodsNameTextView); goodsImageView = itemView.findViewById(R.id.goodsImageView); } } }
8. Implement network loading data
Implement the function of loading product data over the network in MainActivity.java
. Please make sure your goods_list_data.json
file is located in the app/src/main/assets
folder.
package com.leo.network; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.google.gson.Gson; import java.io.IOException; import java.util.Arrays; import java.util.List; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class MainActivity extends AppCompatActivity {<!-- --> private RecyclerView recyclerView; private GoodsAdapter adapter; private List<Goods> goodsList; private static final int MSG_UPDATE_DATA = 1; private Handler msgHandler = new Handler(new Handler.Callback() {<!-- --> @Override public boolean handleMessage(Message msg) {<!-- --> if (msg.what == MSG_UPDATE_DATA) {<!-- --> adapter.notifyDataSetChanged(); } return true; } }); @Override protected void onCreate(Bundle savedInstanceState) {<!-- --> super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(this)); adapter = new GoodsAdapter(this, goodsList); recyclerView.setAdapter(adapter); // Fetch data from the network fetchGoodsData(); } private void fetchGoodsData() {<!-- --> new Thread(new Runnable() {<!-- --> @Override public void run() {<!-- --> try {<!-- --> OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("http://10.0.2.2:8080/goods/goods_list_data.json") .build(); Response response = client.newCall(request).execute(); if (response.isSuccessful()) {<!-- --> String jsonData = response.body().string(); Log.d("Network", "Data fetched successfully: " + jsonData); Gson gson = new Gson(); Goods[] goodsArray = gson.fromJson(jsonData, Goods[].class); //Complete image URL for (Goods goods : goodsArray) {<!-- --> goods.setGoodsPic("http://10.0.2.2:8080//goods" + goods.getGoodsPic()); } goodsList = Arrays.asList(goodsArray); msgHandler.sendEmptyMessage(MSG_UPDATE_DATA); // Switch to the main thread to update the UI runOnUiThread(new Runnable() {<!-- --> @Override public void run() {<!-- --> //Set the adapter of RecyclerView adapter = new GoodsAdapter(MainActivity.this, goodsList); recyclerView.setAdapter(adapter); } }); } } catch (IOException e) {<!-- --> e.printStackTrace(); Log.e("Network", "Error fetching data: " + e.getMessage()); } } }).start(); } }
Replace "URL_TO_YOUR_JSON_DATA"
with the path to your local JSON file, for example: http://localhost:8080/goods/goods_list_data.json
.
Note that if you are deploying tomcat locally and need to access it in the default Android virtualizer, you need to change it to “
10.0.2.2
“
Here are some explanations of the code:
-
A new thread is created in the
fetchGoodsData()
method to perform network requests. This is a good practice because it ensures that network requestsdo not block the main thread to avoid responsiveness issues in your application. -
After the network request is successful, use the Gson library to parse the JSON data into an array of
Goods
objects, and complete the URL of the image. This ensures that Glide loads the image correctly. -
Use
Handler
to update the UI because UI updates must be performed in the main thread. -
When a network request fails, an error message is printed via
Log.e
, which helps with debugging and troubleshooting.
Achieve results