第一行代码网络技术笔记

第一行代码网络技术笔记

1.WebView用法

(1)在注册文件里声明网络权限

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

(2)在布局中定义WebView控件

<WebView
        android:id="@+id/webview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"></WebView>

(3)在MainActivity中

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        WebView webView=(WebView)findViewById(R.id.webview);
        webView.getSettings().setJavaScriptEnabled(true);
        //getSettings()可以设置一些浏览器属性
        webView.setWebViewClient(new WebViewClient());
        //调用setWebViewClient方法,里面传入实例
        //希望当一个网页跳到另一个网页时,目标网页仍然在当前WebView中显示。而不是打开系统浏览器
        webView.loadUrl("http://www.baidu.com");//传入网址
    }
2.HTTP协议访问网络
I. GET&&POST方法

get是从服务器获取数据,几次get没问题。get方法会把请求字段显示在地址栏,不安全。

post向服务器传递数据,执行多次post会向服务器增加n条相同数据。post比较安全。

II.使用HttpUrlConnection

先来一个界面

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
<Button
    android:id="@+id/getbutton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/responseText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </ScrollView>

</LinearLayout>

ScrollView控件可以让页面滚动形式出现,内容多的部分在下面。这里按钮用来发送请求,用TextView接收。

然后处理分二步:构建HttpURLConnection,传入一个URL的openConnection()打开连接,setRequestMethod选择请求方法,有POST和GET供选择。最后要记得disConnection()。

输入流进行处理显示

public class MainActivity extends AppCompatActivity {

    TextView responseText;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button getButton=(Button)findViewById(R.id.getbutton);
        responseText=(TextView)findViewById(R.id.responseText);
        getButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendRequestWithHttpURLConnection();
            }
        });
    }
    private void sendRequestWithHttpURLConnection(){
        //开启线程发起网络请求
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection httpURLConnection=null;
                BufferedReader reader=null;
                try {
                    URL url=new URL("https://www.baidu.com");
                    httpURLConnection=(HttpURLConnection)url.openConnection();
                    httpURLConnection.setRequestMethod("GET");
                    httpURLConnection.setConnectTimeout(8000);
                    httpURLConnection.setReadTimeout(8000);
                    
                    //上传数据这样写
                    //httpURLConnection.setRequestMethod("POST");
                    //DataOutputStream out=new DataOutputStream(httpURLConnection.getOutputStream());
                    //out.writeBytes("username=admin&password=123456");
                    InputStream in=httpURLConnection.getInputStream();
                    //对获取的输入流进行处理
                    reader=new BufferedReader(new InputStreamReader(in));
                    StringBuffer response=new StringBuffer();
                    String line;
                    while ((line=reader.readLine())!=null){
                        response.append(line);
                    }
                    showResponse(response.toString());
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    if(reader!=null){
                        try{
                            reader.close();
                        }catch (IOException e){
                            e.printStackTrace();
                        }
                    }
                    if(httpURLConnection!=null){
                            httpURLConnection.disconnect();
                    }
                }
            }
        }).start();
    }
    private void showResponse(final String response){
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //在这里进行UI操作,显示到界面上,因为子线程不能进行UI操作,所以通过这个函数转移到主线程
                responseText.setText(response);
            }
        });
    }
}

然后在注册文件中添加网络权限

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.networktest">
    <uses-permission android:name="android.permission.INTERNET"/>
III.OkHttp使用

主页地址 https://github.com/square/okhttp

使用步骤

(1)引入依赖

implementation 'com.squareup.okhttp3:okhttp:4.0.1'

(2)AndroidManifest加入网络许可权限

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

(3)使用GET方法

private void sendRequestWithOkHttp(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    OkHttpClient client = new OkHttpClient();
                    Request request=new Request.Builder().url("https://www.baidu.com").build();
                    Response response=client.newCall(request).execute();
                    String responseData=response.body().string();
                    showResponse(responseData);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }).start();
     }

首先构建一个OkHttpClient实例

OkHttpClient client = new OkHttpClient();

然后如果想要发起HTTP请求,就创建一个Request对象,在build前加一系列东西

Request request=new Request.Builder().url(“https://www.baidu.com”).build();

之后调用 OkHttpClient的newCall()方法创建一个Call对象 ,并调用它的execute()方法发送请求和获取服务器返回的数据

Response response=client.newCall(request).execute();

Response对象就是服务器返回的数据了,然后显示出来

String responseData=response.body().string();

(4)使用POST方法

与GET大部分相同,不同的是要构建一个RequestBody对象来存放等待提交的参数

 RequestBody requestBody=new FormBody.Builder().add("username","yuer").build();
 然后Request里添加post()方法将构建好的传进去
// Request request=new Request.Builder().url("https://easy-mock.com/mock/5d2dcaef934181050dd4ae60/hhh/hhh").post(requestBody).build();

(5)还可以封装到一个类的方法里,调用方便
方法这样写
public static void sendOkHttpRequest(String address,okhttp3.Callback callback) {
OkHttpClient okHttpClient=new OkHttpClient();
Request request=new Request.Builder().url(address).build();
okHttpClient.newCall(request).enqueue(callback);
}

//回掉时候

       HttpUtil.sendOkHttpRequest("http://www.baidu.com",new okhttp3.Callback(){
        @Override
        public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
            //得到服务器返回的内容
            String responseData=response.body().string();
        }
        @Override
        public void onFailure(@NotNull Call call, @NotNull IOException e) {
            //对异常进行处理
        }
    });
}
3.网络解析
I.XML格式解析
(1)Pull解析方式

首先我本地模拟XML数据,不进行网络获取

 String xmlData= "<person> \n" +
                            "  <name>张三</name>  \n" +
                            "  <age>23</age> \n" +
                            "</person>";
                    parseXMLWithPull(xmlData);

接下来进行解析

 public void parseXMLWithPull(String xmlData){
        try{
            XmlPullParserFactory xmlPullParserFactory=XmlPullParserFactory.newInstance();
            XmlPullParser xmlPullParser=xmlPullParserFactory.newPullParser();
            xmlPullParser.setInput(new StringReader(xmlData));
            int eventType=xmlPullParser.getEventType();
            String name="";
            String age="";
            while(eventType!=XmlPullParser.END_DOCUMENT){
                String nodeName=xmlPullParser.getName();
                switch (eventType){
                    //开始解析某个结点
                    case XmlPullParser.START_TAG:{
                        if("name".equals(nodeName)){
                            name=xmlPullParser.nextText();
                        }else if("age".equals(nodeName)){
                            age=xmlPullParser.nextText();
                        }
                    }break;
                    //完成解析某个结点
                    case XmlPullParser.END_TAG:{
                        if("person".equals(nodeName)){
                            Log.d("MainActivity","name is"+name);
                            Log.d("MainActivity","age is"+age);
                        }
                        break;
                    }
                    default:break;
                }
                eventType=xmlPullParser.next();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

(1)XmlPullParserFactory.newInstance ()方法其实是返回一个XmlPullParserFactory形式的实例,每次调用构造方法把实例构造出来,那平常的构造法能不能使用呢 XmlPullParserFactory xmlPullParserFactory=new XmlPullParserFactory();我发现报错了,因为构造器是保护类型,protected的作用区域是包内,挎包不能用,这是一种安全措施,但我们还要用这个构造方法咋办呢,一般都像这样,定义一个公开的方法,在里面返回实例。

 /**
     * Creates a new instance of a PullParserFactory that can be used
     * to create XML pull parsers. The factory will always return instances
     * of Android's built-in {@link XmlPullParser} and {@link XmlSerializer}.
     */
    public static XmlPullParserFactory newInstance () throws XmlPullParserException {
        return new XmlPullParserFactory();
    }
/**
 * Protected constructor to be called by factory implementations.
 */
protected XmlPullParserFactory() 


(2) XmlPullParser定义的是一个接口,不是具体实现,所以构建实例的时候采用xmlPullParserFactory.newPullParser();形式

(3)接下来调用.setInput进行数据装填,xmlPullParser.getEventType();获取当前解析事件,然后在while中不断进行解析,如果当前事件不等于XmlPullParser.END_DOCUMENT,说明解析工作还没完成,调用eventType=xmlPullParser.next();方法继续解析下一个结点。

(2)SAX解析方式

SAX解析对比Pull解析要复杂一点,但是代码可读性比较强

首先新定义一个类继承自DefaultHandler,并重写其中五个方法

ublic class MyHandler extends DefaultHandler {
    //开始解析时候调用
    @Override
    public void startDocument() throws SAXException {
        super.startDocument();
    }

    //开始解析某个结点的时候调用  被解析数据以参数形式到下面三个方法中
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
    }

    //获取结点内容时候调用,可能会被调用两次,换行符会调用一次,要做好处理
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
    }

    //结束解析某个结点时候调用
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
    }

    //结束解析时候调用
    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }
}
按照这个思路,我们实现以下上面pull解析方式解析的内容,先重写这几个方法
public class MyHandler extends DefaultHandler {
    String nodeName;
    StringBuilder name;
    StringBuilder age;
    //开始解析时候调用
    @Override
    public void startDocument() throws SAXException {
        //完成变量初始空间分配
        name=new StringBuilder();
        age=new StringBuilder();
    }

    //开始解析某个结点的时候调用  被解析数据以参数形式到下面三个方法中
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        //记录当前结点名
        nodeName=localName;
    }

    //获取结点内容时候调用,可能会被调用两次,换行符会调用一次,要做好处理
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
       //根据当前结点名判断将内容添加到哪一个StringBuffer中
        if("name".equals(nodeName)){
            name.append(ch, start, length);
        }
        else if("age".equals(nodeName)){
            age.append(ch, start, length);
        }
    }

    //结束解析某个结点时候调用
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if("person".equals(nodeName)){
            Log.d("MyHandler","name is "+name.toString().trim());
            Log.d("MyHandler","age is "+age.toString().trim());
            //最后要将StringBuilder清除掉
            name.setLength(0);
            age.setLength(0);
        }
    }

    //结束解析时候调用
    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }
}

接下来就在主程序中调用这个方法

 public void parseXMLWithSAX(String xmlData){
        try{
            SAXParserFactory saxParserFactory=SAXParserFactory.newInstance();
            XMLReader xmlReader=saxParserFactory.newSAXParser().getXMLReader();
            MyHandler handler=new MyHandler();
            //将MyHandler的实例传送到XMLReader中
            xmlReader.setContentHandler(handler);
            //开始执行解析
            xmlReader.parse(new InputSource(new StringReader(xmlData)));
        }catch(Exception e){
            e.printStackTrace();
        }
    }

(3)DOM解析方式

II.JSON格式解析

json格式数据对比SAX简洁,但语义不够多,现在的主流。

(1)用JSONObject 解析json
 public void parseJSONWithOkHttp(String jsonData){
        try{
            JSONArray jsonArray=new JSONArray(jsonData);
            for(int i=0;i<jsonArray.length();i++){
                JSONObject jsonObject=jsonArray.getJSONObject(i);
                String name=jsonObject.getString("name");
                String age=jsonObject.getString("age");
                Log.d("MainActivity","name is "+name);
                Log.d("MainActivity","age is "+age);
            }

        }catch (Exception e){
            e.printStackTrace();
        }
    }
(2)GSON使用

谷歌开发,原理就是将json格式的字符串自动映射为对象,不用手动编写代码解析
它在这里 https://github.com/google/gson
使用方法:
(1)可以查找对应版本引进依赖,在app那个gradle里加上
implementation ‘com.google.code.gson:gson:2.8.5’
(2)预定义一个要解析数据的类,加入解析字段

public class Person {
    private String name;
    private int age;
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name=name;
    }
    public int getAge(){
        return age;
    }
    public void setAge(int age){
        this.age=age;
    }
}

(3)如果要解析的json数据是一段数组要麻烦一些,不是的话可以简单调用下面字段就可以之间变成对象
Gson gson=new Gson();
Person person=gson.fromJson(jsonData,Person.class);
对于数据要借助TypeToken将期望解析的数据类型传入到fromJson中
List

public void parseJsonWithGson(String jsonData){
        Gson gson=new Gson();
        List<Person> peopleList=gson.fromJson(jsonData,new TypeToken<List<Person>>(){}.getType());
        for(Person person:peopleList){
            Log.d("MainActivity","name is "+person.getName());
            Log.d("MainActivity","age is "+person.getAge());
        }
    }


此外还有toJson,可以把数据转换成json格式。

相似功能的还有Fastjson,阿里巴巴的,速度比较快,但对比GSON有一些漏洞。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值