新闻界面

通过ListView实现新闻的界面,android发送请求给服务器,服务器返回需要展示的json数据。android解析新闻数据通过ListView实现图文混排。

为什么使用异步加载:

  • Android单线程模型。

  • 耗时操作阻塞UI进程。

异步加载最常用的两种方式:

  • 1.多线程/线程池

  • 2.AsyncTask

如图所示:

1. 创建项目MyApplication。

2. 创建布局

2.1 主页面

主页面添加ListView组件。

MyApplication/app/src/main/res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="MainActivity">

    <ListView
            android:id="@+id/new_main"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>

</android.support.constraint.ConstraintLayout>

2.2 创建一个Item

就是每一个新闻栏的设计。

MyApplication/app/src/main/res/layout/item_layout.xml

<?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=";horizontal";
    android:layout_width=";match_parent";
    android:layout_height=";wrap_content";
    android:padding=";4dp";>

    <ImageView
            android:id=";@+id/new_pic";
            android:layout_width=";64dp";
            android:layout_height=";64dp";
            android:src=";@mipmap/ic_launcher";/>

    <LinearLayout
            android:layout_width=";match_parent";
            android:layout_height=";match_parent";
            android:orientation=";vertical";>

        <LinearLayout
            android:layout_width=";match_parent";
            android:layout_height=";wrap_content";
            android:layout_weight=";1.5";
            android:orientation=";horizontal";>
            <TextView
                    android:id=";@+id/new_title";
                    android:layout_width=";wrap_content";
                    android:layout_height=";wrap_content";
                    android:text=";Title";
                    android:layout_weight=";1";
                    android:layout_gravity=";center";
                    android:textSize=";20sp";/>
            <TextView
                    android:id=";@+id/new_time";
                    android:layout_width=";wrap_content";
                    android:layout_height=";wrap_content";
                    android:text=";2019-12-28 12:46:00";
                    android:layout_gravity=";center";
                    android:textSize=";13sp";/>

        </LinearLayout>
        <TextView
                android:id=";@+id/new_desc";
                android:layout_width=";wrap_content";
                android:layout_height=";wrap_content";
                android:text=";desc";
                android:layout_weight=";1";
                android:textSize=";15sp";/>

        <TextView
                android:id=";@+id/new_content";
                android:layout_width=";wrap_content";
                android:layout_height=";wrap_content";
                android:text=";content";
                android:visibility=";gone";/>
    </LinearLayout>

</LinearLayout>

2.3. 创建Bean。

MyApplication/app/src/main/java/com/example/myapplication/NewBean.java

package com.example.myapplication;

public class NewBean {

    private String id;
    private String title;
    private String desc;
    private String time;
    private String contentUrl;
    private String picUrl;

    public String getId() {
        return id;
    }

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

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getContentUrl() {
        return contentUrl;
    }

    public void setContentUrl(String contentUrl) {
        this.contentUrl = contentUrl;
    }

    public String getPicUrl() {
        return picUrl;
    }

    public void setPicUrl(String picUrl) {
        this.picUrl = picUrl;
    }
}

2.4. AsyncTask分析

异步请求json数据解析。

MyApplication/app/src/main/java/com/example/myapplication/MainActivity.java

package com.example.myapplication;

import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private ListView mListView;

    private static String URL = "http://news.6liu.top/news";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //默认加载的页面
        setContentView(R.layout.activity_main);
        mListView = (ListView) findViewById(R.id.new_main);

        //发起URL请求
        new NewsAsyncTask().execute(URL);
    }

    /**
     * 实现网络的异步访问
     */
    class NewsAsyncTask extends AsyncTask<String, Void, List<NewBean>>{

        @Override
        protected List<NewBean> doInBackground(String... strings) {
            return getJsonData(strings[0]);
        }

        @Override
        protected void onPostExecute(List<NewBean> newBeans) {
            super.onPostExecute(newBeans);
            NewsAdapter adapter = new NewsAdapter(MainActivity.this, newBeans);
            mListView.setAdapter(adapter);
        }
    }

    /**
     * 将获取到的json数据转化为NewBean对象
     * @param url
     * @return
     */
    private List<NewBean> getJsonData(String url) {
        List<NewBean> newsBeanList = new ArrayList<>();
        try {
            String jsonString = readStream(new URL(url).openStream());
            NewBean newBean;
            //解析Json数据
            JSONObject jsonObject;
            try{
                jsonObject = new JSONObject(jsonString);
                JSONArray jsonArray = jsonObject.getJSONArray("data");
                for (int i=0; i<jsonArray.length(); i++){
                    jsonObject = jsonArray.getJSONObject(i);
                    newBean = new NewBean();
                    newBean.setId(jsonObject.getString("id"));
                    newBean.setTitle(jsonObject.getString("title"));
                    newBean.setDesc(jsonObject.getString("desc"));
                    newBean.setTime(jsonObject.getString("time"));
                    newBean.setContentUrl(jsonObject.getString("content_url"));
                    newBean.setPicUrl(jsonObject.getString("pic_url"));
                    newsBeanList.add(newBean);
                }
            }catch (JSONException e){
                e.printStackTrace();
            }
        } catch (IOException e){
            e.printStackTrace();
        }
        return newsBeanList;
    }

    /**
     * 用is解析网页返回的数据
     * @param is
     * @return
     */
    private String readStream(InputStream is){
        InputStreamReader isr;
        String result = "";
        try {
            String line = "";
            isr = new InputStreamReader(is, "utf-8");
            BufferedReader br = new BufferedReader(isr);
            while ((line = br.readLine()) != null){
                result += line;
            }
        }catch (UnsupportedEncodingException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }
        return result;
    }
}

2.5. 文艺复现BaseAdapter

创建NewsAdapter实现BaseAdapter抽象类放入ListView对象。 MyApplication/app/src/main/java/com/example/myapplication/NewsAdapter.java

package com.example.myapplication;

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

import java.util.List;

public class NewsAdapter extends BaseAdapter {

    private List<NewBean> mList;
    private LayoutInflater mInflater;

    public NewsAdapter(Context context, List<NewBean> data){
        mList = data;
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return mList.size();
    }

    @Override
    public Object getItem(int position) {
        return mList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder = null;
        if(convertView == null){
            viewHolder = new ViewHolder();
            convertView = mInflater.inflate(R.layout.item_layout, null);
            viewHolder.newPic = convertView.findViewById(R.id.new_pic);
            viewHolder.newTitle = convertView.findViewById(R.id.new_title);
            viewHolder.newTime = convertView.findViewById(R.id.new_time);
            viewHolder.newDesc = convertView.findViewById(R.id.new_desc);
            viewHolder.newContent = convertView.findViewById(R.id.new_content);
            convertView.setTag(viewHolder);
        }else{
            viewHolder = (ViewHolder) convertView.getTag();
        }
        #这里图片写死了
        viewHolder.newPic.setImageResource(R.mipmap.ic_launcher);
        viewHolder.newTitle.setText(mList.get(position).getTitle());
        viewHolder.newTime.setText(mList.get(position).getTime());
        viewHolder.newDesc.setText(mList.get(position).getDesc());
        viewHolder.newContent.setText(mList.get(position).getContentUrl());
        return convertView;
    }

    class ViewHolder{
        public TextView newTitle, newTime, newDesc, newContent;
        public ImageView newPic;
    }
}

2.6. 注意

增加网络访问:

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

高版本的api不支持明文访问,就是不支持Http访问,加入一下语句:

android:usesCleartextTraffic="true"

MyApplication/app/src/main/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.myapplication">

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

    <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:usesCleartextTraffic="true"
            android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity android:name="NewsActivity"></activity>
    </application>
</manifest>