首页 > 编程语言 >43.Android 网络编程的简单学习整理

43.Android 网络编程的简单学习整理

时间:2024-05-13 09:20:17浏览次数:23  
标签:编程 43 public JSON new import Android com android

关于Android网络通信编程

Android对HTTP通信提供了支持 通过标准的JAVA类HttpURLConnection便可以实现基于URL的请求及响应功能
关于URL和URI还分不清吗

image

然后还有就是GET和POST方式提交数据

image

注意 使用GET或者POST方式提交参数时 为了防止中文乱码 要对参数进行编码


使用WebView控件进行网络开发

 //Android内置浏览器 使用开源的webkit引擎

来看两个例子:

使用WebView控件浏览网页
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <WebView
        android:id="@+id/webView_page"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
package com.example.four_content;

import android.os.Bundle;
import android.webkit.WebView;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

public class WebViewPage extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview_page);
        //Android内置浏览器 使用开源的webkit引擎
        WebView webView= findViewById(R.id.webView_page);
        //指定要加载的网页(小红书)
        webView.loadUrl("https://www.xiaohongshu.com/explore");
        //WebView控件具备放大和缩小网页的功能
        webView.getSettings().setSupportZoom(true);
        webView.getSettings().setBuiltInZoomControls(true);
    }
}

注意注意 要在清单文件中添加允许访问网络资源的权限

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

效果如图:
image


使用WebView控件执行HTML和JS代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <WebView
        android:id="@+id/webView_html"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <Button
        android:id="@+id/btn_dialog"
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="执行JAVASCRIPT代码并弹出提示框"
        android:layout_margin="8dp"
        android:textColor="@android:color/white"
        android:background="@drawable/btn_dialog_selector"/>
    <WebView
        android:id="@+id/webView_js"
        android:layout_width="300dp"
        android:layout_height="500dp" />
</LinearLayout>
需要注意的点就是:
js代码使用时默认不支持 需要使用方法来设置
package com.example.four_content;

import android.os.Bundle;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.Button;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

public class WebView_html_js extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview_html_js);
        //获取布局控件
        WebView webView_html = findViewById(R.id.webView_html);
        WebView webView_js = findViewById(R.id.webView_js);

        //WebView控件执行html
        // 创建字符串构建器
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("<h2>高地远近</h2>");
        stringBuilder.append("<ul>");
        stringBuilder.append("<li>啊啊</li>");
        stringBuilder.append("<li>哈哈</li>");
        stringBuilder.append("<li>哇哇</li>");
        stringBuilder.append("</ul>");
        //loadDataWithBaseURL方法对比loadData()方法 加载中文的html代码不会乱码
        // 五个参数
        // 1.指定页面使用的url null默认空白页 2.显示的字符串数据 3.显示内容类型 4.数据编码方式 5.进入页面显示的url null默认空白页
        webView_html.loadDataWithBaseURL(null,stringBuilder.toString(),"text/html","utf-8",null);

        //WebView控件执行js代码
        Button button = findViewById(R.id.btn_dialog);
        //指定要加载的网页
        webView_js.loadUrl("file:///android_asset/alert.html");
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //获取WebView控件的WebSettings对象 调用setJavaScriptEnabled()方法使支持js代码
                webView_js.getSettings().setJavaScriptEnabled(true);
                //对于js代码的alert()提示框不加载 需要使用setWebChromeClient()方法实现
                //setWebChromeClient主要处理解析,渲染网页等浏览器做的事情。
                //WebChromeClient是辅助WebView处理JavaScript的对话框,网页图标,图标title,加载进度等
                webView_js.setWebChromeClient(new WebChromeClient());
                webView_js.loadUrl("file:///android_asset/alert.html");
            }
        });
    }
}


JSON数据解析

JSON数据主要有两种结构:

  1. 对象结构
  2. 数组结构
    例如:在进行java开发时候 用postman接口调试 传递JSON数据

image
传的值就是key:value形式

顺便介绍个工具:有很对好用的功能 譬如 JSON数据转JavaBean等等
https://he3.app/zh/

image

言归正传:

JSON解析

Android SDK提供了两种方式解析

  1. JSONObject类和JSONArray类解析
    具体不写了 就是JSONObject类将数据获取 然后JSONArray类输出
    类似之前的隐式显式传递 Bundle方法
  2. 重点使用Gson库解析JSON数据
    可通过fromJson()方法解析JSON数据
    注意: 使用前必须创建JSON数据对应的实体类
    方法对应两种:
1. 对象结构:
        Gson gson = new Gson();
        对象 对象名= gson.fromJson(JSON数据,class);
2. 数组结构:
         Gson gson = new Gson();
        //解析数组结构的JSON数据
        Type listType = new TypeToken<List<实体类>>() {}.getType();
        List<实体类> 名字 = gson.fromJson(JSON数据, listType);

当然使用Gson库需要添加依赖 在此先不说 后面看一个综合案例来说


刨析一个案例之前先看一下Handle机制

image

详细介绍:参考 https://blog.csdn.net/ly0724ok/article/details/117324053
大致就是:
handler其实就是主线程在起了一个子线程,子线程运行并生成Message,Looper获取message并传递给Handler,Handler逐个获取子线程中的Message


来看本篇文章的一个最重要的案例

就是要实现一个仿pdd砍价界面
但是图片来自于网络传输的 也需要用到JSON数据 还有服务器
所以先得准备:

首先tomcat服务器:
将图片和JSON文件放在里面
为的就是通过网络访问到他们

image
关于tomcat运行啊 失败啊 接口占用之类的问题 javaweb的时候都学过了 不过多赘述了
只要你访问8080能够加载出来tomcat官网就行
注意文件放到webapps目录下

然后就是添加需要的依赖:
去这里搜索获取 注意版本问题即可
https://mvnrepository.com/artifact/com.google.code.gson/gson/2.8.5
(这里有坑)

我的使用kts语法
    implementation("com.google.code.gson:gson:2.8.5")
    implementation("com.squareup.okhttp3:okhttp:3.12.0")
    implementation("com.github.bumptech.glide:glide:4.16.0")

书中给的glide是3.7.0的 不支持了 因为我们的是AndroidX 所以用最新的才会支持
https://www.jianshu.com/p/d051c02a485c
但是呢我之前不知道将其添加到library里面 要去删除
image

准备完了前提 来看代码部分
Gson库对应必须的实体类(对应JSON数据)
package com.example.four_content;



public class Goods {
    private int id;
    private String count;
    private String goodsName;
    private String goodsPic;


    public void setId(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setCount(String count) {
        this.count = count;
    }

    public String getCount() {
        return count;
    }

    public void setGoodsName(String goodsName) {
        this.goodsName = goodsName;
    }

    public String getGoodsName() {
        return goodsName;
    }

    public void setGoodsPic(String goodsPic) {
        this.goodsPic = goodsPic;
    }

    public String getGoodsPic() {
        return goodsPic;
    }


}

数据适配器
package com.example.four_content;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;

import java.util.ArrayList;
import java.util.List;

public class PddAdapter extends RecyclerView.Adapter<PddAdapter.MyViewHolder> {
    private Context mcontext;
    private List<Goods> goods = new ArrayList<>();

    public PddAdapter(Context context) {
        this.mcontext = context;
    }

    //获取数据更新界面
    public void setData(List<Goods> goods) {
        this.goods = goods;
        //notifyDataSetChanged方法通过一个外部的方法控制如果适配器的内容改变时需要强制调用getView来刷新每个Item的内容
        // 可以实现动态的刷新列表的功能
        notifyDataSetChanged();
    }


    //      * onCreateViewHolder 加载界面的布局文件 inflate()方法
    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        /**
         *LayoutInflater 是 Android 开发中一个非常重要的类,它的主要作用是将 XML 布局文件转换成相应的视图(View)对象,以便在应用程序的 UI 中使用。
         * inflate 方法是 LayoutInflater 类中的一个核心方法,用于将 XML 布局文件转换为相应的视图对象。
         *  public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)三个参数:
         *  加载的布局文件的资源ID
         * 这是新创建的视图将要被附加到的父视图
         * 用于指定是否立即将新创建的视图附加到父视图上
         * */
        MyViewHolder holder = new MyViewHolder(LayoutInflater.from(mcontext).inflate(R.layout.goods_item, parent, false));
        return holder;
    }


    //      * onBindViewHolder 将获取的数据绑定到对应的控件上

    /**
     * @NonNull MyViewHolder holder: 这是一个非空的视图持有者对象
     * MyViewHolder 通常是开发者自定义的一个类,用于持有列表项中各个视图的引用,从而可以方便地对它们进行操作(如设置文本、图片等)
     * int position: 这是一个整数,表示当前绑定数据的列表项在 RecyclerView 中的位置
     */
    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        Goods been = goods.get(position);
        holder.tv_count.setText("已砍" + been.getCount() + "件");
        holder.tv_goods_name.setText(been.getGoodsName());
        //Glide 是一个快速高效的 Android 图片加载库,可以自动加载网络、本地文件,app 资源中的图片,注重于平滑的滚动
        /**
         * Glide.with(mcontext):
         * 这是 Glide 的一个静态方法,用于创建一个新的图片请求
         *.load(been.getGoodsPic()):
         * 这是指定要加载的图片的 URL、资源 ID 或文件路径的地方
         * error(R.mipmap.ic_launcher):
         * 如果图片加载失败(例如,因为网络错误或无效的 URL),Glide 会显示一个占位符或错误图片。
         * 在这里,如果图片加载失败,Glide 将显示 R.mipmap.ic_launcher,这通常是应用的默认图标
         * .into(holder.iv_img):
         * 这指定了 Glide 应该将图片加载并显示在哪个ImageView上
         * */
        Glide.with(mcontext)
                .load(been.getGoodsPic())
                .error(R.mipmap.ic_launcher)
                .into((holder).iv_img);
    }


    //      * getItemCount 获取列表条目的总数
    @Override
    public int getItemCount() {
        return goods.size();
    }


    //强制使用ViewHolder 使代码编写规范化 想当与listview中的优化

    class MyViewHolder extends RecyclerView.ViewHolder {
        TextView tv_count, tv_goods_name;
        ImageView iv_img;
        Button btn_free;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            tv_count = itemView.findViewById(R.id.tv_count);
            tv_goods_name = itemView.findViewById(R.id.tv_goods_name);
            iv_img = itemView.findViewById(R.id.iv_img);
            btn_free = itemView.findViewById(R.id.btn_free);
        }
    }
}

package com.example.four_content;


import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;


import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.List;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class PDDActivity extends AppCompatActivity {
    private static final int MSG_GOODS_OK = 1;
    //内网接口
    public static final String Web_SITE = "http://127.16.43.20:8080/goods";
    //商品列表接口
    public static final String REQUEST_GOODS_URL = "/goods_list_data.json";

    private MHandle mHandle;

    private PddAdapter pddAdapter;


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pdd);
        /**
         * 1.获取列表框架
         * 2.创建一个适配器 可以用已有的 亦可以创建继承的自己的
         * 3.将适配器添加到列表框架中
         * */
        RecyclerView rv_list = findViewById(R.id.rv_list);
        pddAdapter = new PddAdapter(PDDActivity.this);
        rv_list.setAdapter(pddAdapter);
        //GridLayoutManager,这是一个RecyclerView的布局管理器,它可以将项目以网格的形式展示
        GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2);
        rv_list.setLayoutManager(gridLayoutManager);
        //Handler消息机制
        mHandle = new MHandle();
        initData();
    }


    //开启异步线程访问网络
    private void initData() {
        OkHttpClient okHttpClient = new OkHttpClient();
        Request request = new Request.Builder().url(Web_SITE + REQUEST_GOODS_URL).build();
        Call call = okHttpClient.newCall(request);
        //消息队列 存储消息
        call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String string = response.body().string();
                Message message = new Message();
                message.obj = string;
                message.what = MSG_GOODS_OK;
                //发送消息
                mHandle.sendMessage(message);
            }
            @Override
            public void onFailure(Call call, IOException e) {
            }
        });
    }


    //处理消息
    class MHandle extends Handler {
        @Override
        public void dispatchMessage(@NonNull Message msg) {
            super.dispatchMessage(msg);
            if (msg.what == MSG_GOODS_OK) {
                if (msg.obj != null) {
                    String result = (String) msg.obj;
                    List<Goods> goodsList = getGoodsList(result);
                    pddAdapter.setData(goodsList);
                }
            }
        }
    }


    //Gson库解析JSON数据
    public List<Goods> getGoodsList(String json) {
        Gson gson = new Gson();
        //解析数组结构的JSON数据
        Type listType = new TypeToken<List<Goods>>() {}.getType();
        List<Goods> goods = gson.fromJson(json, listType);
        return goods;
    }

}

上述跳过了layout布局文件
运行后:
image

为何不显示呢 因为是网络访问 需要将程序运行到第三方模拟器上

这里以夜神模拟器为例:
参考 https://blog.csdn.net/My_Deng_Peng/article/details/82153940

启动连接
image

内部找到
image


补充 我上面说错了 不是因为模拟器的原因 而是网络访问的问题 还有就是设置IP的问题:

当然上面就当学习第三方模拟器了:

https://zhuanlan.zhihu.com/p/112957829
参考 你会发现夜神模拟器不兼容 可以使用上述很详细介绍

咱主要来看看错误的原因 就是:IP地址需要是你本机的地址

image
参考 https://blog.csdn.net/weixin_44734310/article/details/108550307

这里使用Mumu模拟器

我们会发现还没加载出来

坑坑坑:

image
需要配置此项:

网络资源加载失败 http访问问题
参考:https://www.cnblogs.com/zhangwenju/p/14240765.html
终于终于:
image
别忘记开启tomcat服务

标签:编程,43,public,JSON,new,import,Android,com,android
From: https://www.cnblogs.com/gaodiyuanjin/p/18185863

相关文章

  • Spark - [04] RDD编程
    题记部分 一、RDD编程模型  在Spark中,RDD被表示为对象,通过对象上的方法调用来对RDD进行转换。经过一系列的transformations定义RDD之后,就可以调用actions触发RDD的计算,action可以是向应用程序返回结果(count,collect等),或者是向存储系统保存数据(saveAsTextFile......
  • Android开发&Kotlin学习笔记
    为了做《基于安卓定位的考勤系统》,学了一些杂乱的知识,在这里简单记录一下。除了在C#桌面应用开发中感性的体会到了些XML布局的知识以及课上学习的Java知识,其他也算是零基础了。GoogleAndroidDeveloper的课程2023/10/25:跟着官方文档先快速入门一下基本内容。截至目前来看官方......
  • 编程竞赛中 C/C++ I/O 的使用
    C的字符串读取scanf以空行为分割进行读取数据。get和fgets以\n为分割读取数据。读取输入直到遇到\n或\0才终止。C++读取字符串cin以空格为分割读取数据。getline默认以换行符为分割读取数据。在使用getline时,要注意处理多个\n连到一块的情况。当读取77\n\n77时,......
  • 14.GUI 编程
    1.GUI编程简介GUI:图形用户界面GUI核心技术:Swing、Awt类界面不美观需要jre环境为什么要学习:可以写出一些小工具工作时候,也可能需要维护到Swing界面,概率绩效了解MVC架构,了解监听2.AWT类2.1.Awt介绍包含了很多类和接口元素:窗口、按钮、文本框java.awt包......
  • luogu P4342[IOI1998]Polygon
    阅读前需深剖析分系列是记录我个人的做题思路,实现过程的全面分析,存在内容可靠、思路健全、分析到位、试错纠错等优于一般题解的特征,其中,Quest部分表示探索问题,我会在此提出做题时的想法、问题,并在内容中得到解决,因此建议从上到下按序浏览,以防出现思路断层,内容不衔接的情况,感谢理......
  • LOTO示波器动作编程功能(命令批处理)
     动作编程功能是为了方便客户根据自己的应用场景,做到一个按键就连续做多个示波器操作,从而降低了对操作人员的技术要求,做到傻瓜式操作。之前LOTO有个类似的功能,是把示波器的基础设置根据不同的测试场景存成不同的设置文件,需要时可以选择合适的场景设置导入进来这个设置文件。它和......
  • C++_函数式编程-以及常用序列化
    函数式编程函数式编程是一种编程范式,它强调程序的构建是通过应用(applying)和组合函数(composingfunctions)来实现的函数式编程属于“结构化编程”的一种,主要思想是把运算过程尽量写成一系列嵌套的函数调用 LambdaCalculus函数式编程语言早期的函数式......
  • android中Room数据库的基本使用
    简介:还在使用原生的sqllite?有这么清爽且稳如狗的room为啥不用呢?Room是Google官方推荐使用的数据库,相比较某些优秀数据库框架来说,不用过于担心某天库会停止维护,且访问数据库非常流畅,并且提供了与常规的ORM框架一样,通过添加编译期注解来进行表和字段的配置,譬如@Database、@Dao、@E......
  • 嵌入式系统设计的轻量级框架+在Linux中用于外围设备访问C库+自研的编程语言和集成开发
    1、mr-library-一个专为嵌入式系统设计的轻量级框架mr-library是一个专为嵌入式系统设计的轻量级框架,模块化的软件架构充分考虑了嵌入式系统的资源和性能要求。通过提供标准化的设备管理等,极大地简化了嵌入式应用的开发难度,帮助开发者快速构建嵌入式应用程序。设备框架 为......
  • Android Studio简单入门教程
    1.建立项目首先点击new——newproject新建项目选择想要创建的Android的模板,建议选择emptyactivity(空模板),然后nextName:给你的项目起一个名字APIlevel:选择Android虚拟机的版本,版本越低运行起来越快剩下的就按默认的就行,点击finish(由于版本不一样,步骤2和步骤3的顺序......