Android基础(三):网络请求

网络请求

Http的常用请求方式有:


image.png

Get&Post:
网络请求中我们常用键值对来传输参数。

JSON

JSON(JavaScript Object Notation)是一种基于文本的数据交换格式。无论你的应用是用哪种开发语言编写的(Java/EE,Ruby,PHP,C#/.Net等等),你都可以使用JSON来通过网络进行数据交互和处理。
JSON是一种简单数据格式,它有三种数据结构:

  • 键值对 —— Name/Value (Key/Value)
  • 对象 —— Object
  • 数组 —— Arrays

用Android原生技术解析JSON:
1、解析JSON对象的API:JsonObject
JSONObject(String json);将Json字符串解析成Json对象;
XxxgetXxx(String name) ;根据name在json对象中得到相应的value。

//获取JSON数据
final String content = response.body().string();
JSONObject jsonObject = null;
try {
    //解析JSON对象
    jsonObject = new JSONObject(content);
    JSONObject result = jsonObject.optJSONObject("result");
    final int detailid = result.optInt("detailid");
    final String title = result.optString("title");
    final String type = result.optString("type");
    String c = result.optString("content");
    // 封装Java对象
    detailModel = new DetailModel(detailid, title, type, c);
    System.out.println(detailModel);
    handler.post(new Runnable() {
        @Override
        public void run() {
            Log.d("PoetryTag", "detailid:" + detailid + ", title:" + title + ", type:" + type + ", content:" + content);
            //显示解析后的数据
            tv_title.setText(detailModel.getTitle());
            tv_type.setText(detailModel.getType());
            tv_content.setText(Html.fromHtml(detailModel.getContent()));
        }
    });
} catch (JSONException e) {
    e.printStackTrace();
}

2、解析Json数组的API:JSONArray
JSONArray(String json);将json字符串解析成json数组;
int length();得到json数组中元素的个数;
XxxgetXxx(int s) ;根据下标得到json数组中对应的元素数据。

private List<PoetryModel> data(String content) {
    List<PoetryModel> poetryModels = new ArrayList<>();
    try {
        //解析json数组
        JSONObject jsonObject = new JSONObject(content);
        JSONArray jsonArray = jsonObject.optJSONArray("result");

        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject object = jsonArray.getJSONObject(i);
            if (object != null) {
                int detailid = object.optInt("detailid");
                String name = object.optString("name");
                String author = object.optString("author");
                // 封装Java对象
                PoetryModel poetryModel = new PoetryModel(detailid, name, author);
                //显示解析后的数据
                poetryModels.add(poetryModel);
                Log.d("PoetryTag", "detail:" + detailid + ", name:" + name + ", author:" + author);
            }
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return poetryModels;
}

OkHttp

导入Jar包

implementation 'com.squareup.okhttp3:okhttp:3.2.0’

在日常开发中最常用到的网络请求就是GET和POST两种请求方式。

  • Requests(请求)
    每一个HTTP请求中都应该包含一个URL,一个GET或POST方法以及Header或其他参数,当然还可以含特定内容类型的数据流。
  • Responses(响应)
    响应则包含一个回复代码(200代表成功,404代表未找到),Header和定制可选的body。
final OkHttpClient client = new OkHttpClient();

public void run(int id) {

    Request request = new Request.Builder()

            .url("[https://api.jisuapi.com/tangshi/detail?appkey=ccb0bd990f91c687&detailid=](https://api.jisuapi.com/tangshi/detail?appkey=ccb0bd990f91c687&detailid=)" + id)

            .get()

            .build();

    client.newCall(request).enqueue(new Callback() {

        @Override

        public void onFailure(Call call, IOException e) {

            e.printStackTrace();

        }

        @Override

        public void onResponse(Call call, Response response) throws IOException {

            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

        // ...JSON解析... 

}
  • 同步&异步
    这2个概念仅存在于多线程编程中。
    android中默认只有一个主线程,也叫UI线程。因为View绘制只能在这个线程内进行。
    所以如果你阻塞了(某些操作使这个线程在此处运行了N秒)这个线程,这期间View绘制将不能进行,UI就会卡。所以要极力避免在UI线程进行耗时操作。
    网络请求是一个典型耗时操作。
    同步:直接耗时操作阻塞线程直到数据接收完毕然后返回。Android不允许的。
    异步:在子线程进行耗时操作,完成后通过Handler将更新UI的操作发送到主线程执行。

使用handler中的post方法:

handler.post(new Runnable() {
    @Override
    public void run() {
        Log.d("PoetryTag", "detailid:" + detailid + ", title:" + title + ", type:" + type + ", content:" + content);
        //显示解析后的数据
        tv_title.setText(detailModel.getTitle());
        tv_type.setText(detailModel.getType());
        tv_content.setText(Html.fromHtml(detailModel.getContent()));
    }
});

这样处理的话我们就可以不用重写handlerMessage()方法了,适合子线程与主线程进行较为单一的交流。

实例:

MainActivity:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button bt_get;
    private Button bt_post;
    private PoetryAdapter adapter;
    private RecyclerView recycler;

    final OkHttpClient client = new OkHttpClient();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        recycler = findViewById(R.id.recycler);
        recycler.setLayoutManager(new LinearLayoutManager(this, RecyclerView.VERTICAL, false));

        bt_get = findViewById(R.id.bt_get);
        bt_post = findViewById(R.id.bt_post);

        bt_get.setOnClickListener(this);
        bt_post.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.bt_get:
                run();
                try {
                    run();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
        }
    }

    private void getRequest() {

        final Request request = new Request.Builder()
                .get()
                .tag(this)
                .url("https://api.apiopen.top/recommendPoetry")
                .build();

        new Thread(new Runnable() {
            @Override
            public void run() {
                Response response = null;
                try {
                    response = client.newCall(request).execute();
                    if (response.isSuccessful()) {
                        Log.i("WY", "打印GET响应的数据:" + response.body().string());
                    } else {
                        throw new IOException("Unexpected code " + response);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public void run() {

        Request request = new Request.Builder()
                .url("https://api.jisuapi.com/tangshi/chapter?appkey=ccb0bd990f91c687")
                .get()
                .build();

        client.newCall(request).enqueue(new Callback() {

            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

                String content = response.body().string();
                final List<PoetryModel> poetryModels = data(content);

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        PoetryAdapter adapter = new PoetryAdapter(poetryModels);
                        recycler.setAdapter(adapter);

                        adapter.setOnItemClickListener(new PoetryAdapter.OnItemClickListener() {
                            @Override
                            public void onItemClick(PoetryModel poetryModel) {
                                Intent intent = new Intent(MainActivity.this,DetailActivity.class);
                                intent.putExtra("entity",poetryModel);
                                startActivity(intent);
                            }
                        });
                    }
                });
            }
        });
    }

    private List<PoetryModel> data(String content) {
        List<PoetryModel> poetryModels = new ArrayList<>();

        try {
            //解析json数组
            JSONObject jsonObject = new JSONObject(content);
            JSONArray jsonArray = jsonObject.optJSONArray("result");
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject object = jsonArray.getJSONObject(i);

                if (object != null) {

                    int detailid = object.optInt("detailid");
                    String name = object.optString("name");
                    String author = object.optString("author");
                    // 封装Java对象
                    PoetryModel poetryModel = new PoetryModel(detailid, name, author);
                    //显示解析后的数据
                    poetryModels.add(poetryModel);

                    Log.d("PoetryTag", "detail:" + detailid + ", name:" + name + ", author:" + author);
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return poetryModels;
    }
}

DetailAcivity:

public class DetailActivity extends AppCompatActivity {

    private TextView tv_title;
    private TextView tv_type;
    private TextView tv_content;
    private DetailModel detailModel;
    private PoetryModel poetryModel;

    private Handler handler = new Handler();

    final OkHttpClient client = new OkHttpClient();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);

        tv_title = findViewById(R.id.tv_title);
        tv_type = findViewById(R.id.tv_type);
        tv_content = findViewById(R.id.tv_content);

        poetryModel = getIntent().getParcelableExtra("entity");

        run(poetryModel.getDetailid());
    }

    public void run(int id) {
        Request request = new Request.Builder()
                .url("https://api.jisuapi.com/tangshi/detail?appkey=ccb0bd990f91c687&detailid=" + id)
                .get()
                .build();

        client.newCall(request).enqueue(new Callback() {

            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

                //获取JSON数据
                final String content = response.body().string();

                JSONObject jsonObject = null;
                try {
                    //解析JSON对象
                    jsonObject = new JSONObject(content);
                    JSONObject result = jsonObject.optJSONObject("result");

                    final int detailid = result.optInt("detailid");
                    final String title = result.optString("title");
                    final String type = result.optString("type");
                    String c = result.optString("content");

                    // 封装Java对象
                    detailModel = new DetailModel(detailid, title, type, c);
                    System.out.println(detailModel);

                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            Log.d("PoetryTag", "detailid:" + detailid + ", title:" + title + ", type:" + type + ", content:" + content);
                            //显示解析后的数据
                            tv_title.setText(detailModel.getTitle());
                            tv_type.setText(detailModel.getType());
                            tv_content.setText(Html.fromHtml(detailModel.getContent()));
                        }
                    });
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

运行结果:


image.png

image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容