【0037】Android基础-25-新闻客户端添加网络支持

【1】配置服务器

配置好的服务器可以使用地址:直接访问并返回json数据;

在sqlite软件中执行下面指令:

【指令1】创建数据库

【指令2】创建数据中的表:复制到到命令区,然后执行;

 1 -- phpMyAdmin SQL Dump
 2 -- http://www.phpmyadmin.net
 3 --
 4 -- 生成日期: 2015080823:15
 5 
 6 SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
 7 SET time_zone = "+00:00";
 8 
 9 
10 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
11 /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
12 /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
13 /*!40101 SET NAMES utf8 */;
14 
15 --
16 -- 数据库: `ahaUomrdcFSIMZUucMBS`
17 --
18 
19 -- --------------------------------------------------------
20 
21 
22 --
23 -- 表的结构 `news`
24 --
25 
26 CREATE TABLE IF NOT EXISTS `news` (
27   `id` int(11) NOT NULL,
28   `title` varchar(300) NOT NULL,
29   `des` varchar(300) NOT NULL,
30   `icon_url` varchar(200) NOT NULL,
31   `news_url` varchar(200) NOT NULL,
32   `type` int(20) NOT NULL,
33   `comment` int(20) NOT NULL,
34   `time` varchar(100) NOT NULL,
35   PRIMARY KEY (`id`),
36   UNIQUE KEY `id` (`id`),
37   KEY `id_2` (`id`)
38 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
39 
40 --
41 -- 转存表中的数据 `news`
42 --
43 
44 INSERT INTO `news` (`id`, `title`, `des`, `icon_url`, `news_url`, `type`, `comment`, `time`) VALUES
45 (0, '刘强东与奶茶妹妹领证结婚 有图为证', '凤凰科技讯 8月8日消息,今天有网友爆料,京东创始人兼CEO刘强东已与奶茶妹妹章泽天在朝阳区民政局领证结婚。', 'http://d.ifengimg.com/mw604/y3.ifengimg.com/ifengimcp/pic/20150808/ce1b80056cfc584fafbf_size20_w450_h800.jpg', 'http://i.ifeng.com/news/sharenews.f?aid=100435430', 2, 3000, ''),
46 (1, '苹果或于9月9日发布iPhone6s 火狐爆严重漏洞', '苹果iPhone6s发布的具体时间越传越近了,但至今还没有官方的准信儿。今天还是让我们关注一下火狐漏洞吧。火狐浏览器开发商Mozilla提醒用户立即升级到最新版本,最好还要修改密码和登录信息。', 'http://img.jiemian.com/101/original/20150808/143899303035536900_a580x330.jpg', 'http://m.jiemian.com/article/347958.html', 3, 1200, ''),
47 (2, '升还是不升:Win7、Win10全面对比评测', '7月29日,历经9个月数百万人内测完善之后,微软终于发布Win10正式版系统。但是可能对于部分用户而言,Win7仍然是绝对的经典、游戏玩家的不二之选,为何非要升级到Win10系统呢?Windows10性能和功能相比Windows7,有提升吗?下面IT之家就为大家带来Win7与Win10功能与性能的正面PK,相信还在犹豫不决的用户看完本文心里就会有了答案。', 'http://p2.pstatp.com/large/6850/6105376239', 'http://toutiao.com/a5229867988/', 1, 5000, '');
48 
49 /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
50 /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
51 /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

 

【1.1】在线校验json数据的网站:www.bejson.com

【服务器启动】需要启动服务器

服务器代码地址:http://pan.baidu.com/s/1qY0sdkw

 

【2】代码逻辑

【3】从服务器获取数据,然后进行解析后显示在ListView中:

【源码】

【MainActivity.java】源码

  1 /**
  2  * MainActivity.java
  3  */
  4 package com.itheima.news_listview;
  5 
  6 import java.util.ArrayList;
  7 
  8 import com.itheima.news_listview.adapter.NewsAdapter;
  9 import com.itheima.news_listview.bean.NewsBean;
 10 import com.itheima.news_listview.utils.NewsUtils;
 11 
 12 import android.app.Activity;
 13 import android.content.Context;
 14 import android.content.Intent;
 15 import android.net.Uri;
 16 import android.os.Bundle;
 17 import android.os.Handler;
 18 import android.os.Message;
 19 import android.view.View;
 20 import android.widget.AdapterView;
 21 import android.widget.AdapterView.OnItemClickListener;
 22 import android.widget.ListView;
 23 import android.widget.Toast;
 24 
 25 public class MainActivity extends Activity implements OnItemClickListener {
 26 
 27     private Context mContext;
 28 
 29 
 30     private Handler handler = new Handler(){
 31         public void handleMessage(android.os.Message msg) {
 32 
 33             ArrayList<NewsBean> allNews = (ArrayList<NewsBean>) msg.obj;
 34 
 35             if(allNews != null && allNews .size()>0)
 36             {
 37                 //3.创建一个adapter设置给listview
 38                 NewsAdapter newsAdapter = new NewsAdapter(mContext, allNews);
 39                 lv_news.setAdapter(newsAdapter);
 40             }
 41 
 42         };
 43     };
 44 
 45 
 46     private ListView lv_news;
 47 
 48 
 49     @Override
 50     protected void onCreate(Bundle savedInstanceState) {
 51         super.onCreate(savedInstanceState);
 52         setContentView(R.layout.activity_main);
 53         mContext = this;
 54         lv_news = (ListView) findViewById(R.id.lv_news);
 55 
 56         //1.先去数据库中获取缓存的新闻数据展示到listview
 57         ArrayList<NewsBean> allnews_database = NewsUtils.getAllNewsForDatabase(mContext);
 58 
 59         if(allnews_database !=null && allnews_database.size()>0){
 60             //创建一个adapter设置给listview
 61             NewsAdapter newsAdapter = new NewsAdapter(mContext, allnews_database);
 62             lv_news.setAdapter(newsAdapter);
 63         }
 64 
 65         //2.通过网络获取服务器上的新闻数据用list封装 ,获取网络数据需要在子线程中做
 66         new Thread(new Runnable() {
 67 
 68             @Override
 69             public void run() {
 70 
 71                 
 72                 //请求网络数据
 73                 ArrayList<NewsBean> allNews = NewsUtils.getAllNewsForNetWork(mContext);
 74                 //通过handler将msg发送到主线程去更新Ui
 75                 Message msg = Message.obtain();
 76                 msg.obj = allNews;
 77                 handler.sendMessage(msg);
 78 
 79 
 80             }
 81         }).start();
 82 
 83 
 84         //3.设置listview条目的点击事件
 85         lv_news.setOnItemClickListener(this);
 86 
 87 
 88 
 89 
 90 
 91     }
 92     //listview的条目点击时会调用该方法 parent:代表listviw  view:点击的条目上的那个view对象   position:条目的位置  id: 条目的id
 93     @Override
 94     public void onItemClick(AdapterView<?> parent, View view, int position,
 95             long id) {
 96 
 97         //需要获取条目上bean对象中url做跳转
 98         NewsBean bean = (NewsBean) parent.getItemAtPosition(position);
 99 
100         String url = bean.news_url;
101 
102         //跳转浏览器
103         Intent intent = new Intent();
104         intent.setAction(Intent.ACTION_VIEW);
105         intent.setData(Uri.parse(url));
106         startActivity(intent);
107     }
108 
109 
110 }

【javabean的封装】

 1 /* NewsBean.java 源码*/
 2 package com.itheima.news_listview.bean;
 3 
 4 import android.graphics.Bitmap;
 5 import android.graphics.drawable.Drawable;
 6 
 7 public class NewsBean {
 8 
 9     public String title;
10     public String des;
11     public String news_url;
12     public int id;
13     public int comment;
14     public int type;
15     public String time;
16     public String icon_url;        
17 }

【NewsUtils.java源码】

 1 /*NewsUtils.java源码 */
 2 package com.itheima.news_listview.utils;
 3 
 4 import java.io.InputStream;
 5 import java.net.HttpURLConnection;
 6 import java.net.URL;
 7 import java.net.URLConnection;
 8 import java.util.ArrayList;
 9 
10 import org.json.JSONArray;
11 import org.json.JSONObject;
12 
13 import android.content.Context;
14 
15 import com.itheima.news_listview.R;
16 import com.itheima.news_listview.bean.NewsBean;
17 import com.itheima.news_listview.dao.NewsDaoUtils;
18 
19 public class NewsUtils {
20 
21 
22     public static String newsPath_url = "http://192.168.13.83:8080/itheima74/servlet/GetNewsServlet";
23     //封装新闻的假数据到list中返回
24     public static ArrayList<NewsBean> getAllNewsForNetWork(Context context) {
25         ArrayList<NewsBean> arrayList = new ArrayList<NewsBean>();
26         try{
27             //1.请求服务器获取新闻数据
28             //获取一个url对象,通过url对象得到一个urlconnnection对象
29             URL url = new URL(newsPath_url);
30             HttpURLConnection connection = (HttpURLConnection) url.openConnection();
31             //设置连接的方式和超时时间
32             connection.setRequestMethod("GET");
33             connection.setConnectTimeout(10*1000);
34             //获取请求响应码
35             int code = connection.getResponseCode();
36             if(code == 200){
37                 //获取请求到的流信息
38                 InputStream inputStream = connection.getInputStream();
39                 String result = StreamUtils.streamToString(inputStream);
40                 
41                 //2.解析获取的新闻数据到List集合中。
42                 
43                     JSONObject root_json = new JSONObject(result);//将一个字符串封装成一个json对象。
44                     JSONArray jsonArray = root_json.getJSONArray("newss");//获取root_json中的newss作为jsonArray对象
45                     
46                     for (int i = 0 ;i < jsonArray.length();i++){//循环遍历jsonArray
47                         JSONObject news_json = jsonArray.getJSONObject(i);//获取一条新闻的json
48                         
49                         NewsBean newsBean = new NewsBean();
50                         
51                         newsBean. id = news_json.getInt("id");
52                         newsBean. comment = news_json.getInt("comment");//评论数
53                         newsBean. type = news_json.getInt("type");//新闻的类型,0 :头条 1 :娱乐 2.体育
54                         newsBean. time = news_json.getString("time");
55                         newsBean. des = news_json.getString("des");
56                         newsBean. title = news_json.getString("title");
57                         newsBean. news_url = news_json.getString("news_url");
58                         newsBean. icon_url = news_json.getString("icon_url");
59                         
60                         arrayList.add(newsBean);
61             
62                     }
63 
64                 //3.清楚数据库中旧的数据,将新的数据缓存到数据库中
65                     new NewsDaoUtils(context).delete();
66                     new NewsDaoUtils(context).saveNews(arrayList);
67             }
68             
69         }catch (Exception e) {
70             e.printStackTrace();
71         }
72         return arrayList;
73     }
74     
75     //从数据库中获取上次缓存的新闻数据做listview的展示
76     public  static ArrayList<NewsBean> getAllNewsForDatabase(Context context) {
77         
78         return new NewsDaoUtils(context).getNews();
79 
80     }
81 }

【StreamUtils.java】源码

 1 /**
 2  * StreamUtils.java
 3  * 功能:主要完成stream到字符串的转换
 4  */
 5 package com.itheima.news_listview.utils;
 6 
 7 import java.io.ByteArrayOutputStream;
 8 import java.io.InputStream;
 9 
10 public class StreamUtils {
11 
12     public static String streamToString(InputStream  in){
13         String result ="";
14 
15         try{
16             //创建一个字节数组写入流
17             ByteArrayOutputStream out = new ByteArrayOutputStream();
18             
19             byte[] buffer = new byte[1024];
20             int length = 0;
21             while (  (length =  in.read(buffer)) !=-1) {
22                 out.write(buffer, 0, length);
23                 out.flush();
24             }
25             
26             result =   new String(out.toByteArray(),"gbk");
27             
28 //            result = out.toString();//将字节流转换成string
29             
30             out.close();
31         }catch (Exception e) {
32             e.printStackTrace();
33         }
34         return result;
35     }
36 }

 

【4】APP访问主机的名称需要修改,否则无法访问

 

【5】数据解析出来是乱码,因为Android的编码是utf-8的编码

 

 

【解决方法1】服务器端改为utf-8的编码,然后重启服务器;

【解决方法2】在APP端进行编码的更改

【6】显示效果

【7】【功能】将在服务器获取的数据缓存到数据库中

【7.1】APP中的数据库的创建

一般会封装两个类,一个是数据的创建,一个是数据库的增删改查

【NewsOpenHelper.java源码】帮助类功能:完成表的创建;

 1 /**
 2  * NewsOpenHelper.java源码
 3  */ 
 4  
 5 package com.itheima.news_listview.dao;
 6 
 7 import android.content.Context;
 8 import android.database.sqlite.SQLiteDatabase;
 9 import android.database.sqlite.SQLiteDatabase.CursorFactory;
10 import android.database.sqlite.SQLiteOpenHelper;
11 
12 public class NewsOpenHelper extends SQLiteOpenHelper {
13 
14     public NewsOpenHelper(Context context) {
15         super(context, "heimanews1", null, 1);
16     }
17 
18     @Override
19     public void onCreate(SQLiteDatabase db) {
20 /*        newsJson.put("id", newsBean.getId());
21         newsJson.put("title", newsBean.getTitle());
22         newsJson.put("des", newsBean.getDes());
23         newsJson.put("icon_url", newsBean.getIcon_url());
24         newsJson.put("news_url", newsBean.getNews_url());
25         newsJson.put("type", newsBean.getType());
26         newsJson.put("time", newsBean.getTime());
27         newsJson.put("comment", newsBean.getComment());*/
28         db.execSQL("create table news (_id integer  ,title varchar(200),des varchar(300),icon_url varchar(200),news_url varchar(200)," +
29                 " type integer , time varchar(100),comment integer)");
30     }
31 
32     @Override
33     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
34         // TODO Auto-generated method stub
35 
36     }
37 
38 }

  【NewsDaoUtils.java】源码:完成数据库中的数据删除、增加、获取数据

 1 //NewsDaoUtils.java
 2 package com.itheima.news_listview.dao;
 3 
 4 import java.util.ArrayList;
 5 
 6 import com.itheima.news_listview.bean.NewsBean;
 7 
 8 import android.content.ContentValues;
 9 import android.content.Context;
10 import android.database.Cursor;
11 import android.database.sqlite.SQLiteDatabase;
12 
13 public class NewsDaoUtils {
14 
15     private NewsOpenHelper newsOpenHelper;
16 
17     public NewsDaoUtils(Context context){
18 
19         //创建一个帮助类对象
20         newsOpenHelper = new NewsOpenHelper(context);
21 
22     }
23 
24     //删除数据库中缓存的旧数据
25     public void delete(){
26 
27         //通过帮助类对象获取一个数据库操作对象
28         SQLiteDatabase db = newsOpenHelper.getReadableDatabase();
29         db.delete("news", null, null);
30         db.close();
31     }
32 
33     //向数据库中添加新闻数据
34     public void saveNews(ArrayList<NewsBean> list){
35 
36         //通过帮助类对象获取一个数据库操作对象
37         SQLiteDatabase db = newsOpenHelper.getReadableDatabase();
38         for (NewsBean newsBean : list) {
39             ContentValues values = new ContentValues();
40             values.put("_id", newsBean.id);
41             values.put("title", newsBean.title);
42             values.put("des", newsBean.des);
43             values.put("icon_url", newsBean.icon_url);
44             values.put("news_url", newsBean.news_url);
45             values.put("type", newsBean.type);
46             values.put("time", newsBean.time);
47             values.put("comment", newsBean.comment);
48             db.insert("news", null, values);
49 
50         }
51 
52         db.close();
53     }
54 
55     //从数据库中获取缓存的新闻数据
56     public ArrayList<NewsBean> getNews(){
57         ArrayList<NewsBean> list = new ArrayList<NewsBean>();
58         //通过帮助类对象获取一个数据库操作对象
59         SQLiteDatabase db = newsOpenHelper.getReadableDatabase();
60         Cursor cursor = db.rawQuery("select * from news", null);//查询获取数据
61 
62         if(cursor != null && cursor.getCount() > 0){
63 
64             while(cursor.moveToNext()){
65 
66                 NewsBean newsBean = new NewsBean();
67                 newsBean. id = cursor.getInt(0);
68                 newsBean. title = cursor.getString(1);
69                 newsBean. des =    cursor.getString(2);
70                 newsBean. icon_url =    cursor.getString(3);
71                 newsBean. news_url =    cursor.getString(4);
72                 newsBean.     type = cursor.getInt(5);
73                 newsBean. time =    cursor.getString(6);
74                 newsBean.     comment = cursor.getInt(7);
75 
76                 list.add(newsBean);
77             }
78         }
79 
80         db.close();
81         cursor.close();
82 
83 
84         return list;
85 
86     }
87 
88 
89 
90 }

 【7.2】将获取的数据保存到数据库中

 

【8】在APP再次打开的时候将数据库中的数据还原到APP中

 

 

 【9】为了本次(第二次)打开APP后,能够只在本地APP的数据库中只缓存上次(第一次)次显示的数据,需要在保存上次(第一次)保存数据时,

清空数据库中的数据。即,APP数据库中只缓存本次显示过的数据;

【备注】即使不清空也不会影响,因为在本地数据库中_id是主键,不会存在重复的新闻条目的;

 

 【10】防止空白数据的返回

【11】增加评论数据和分类数据

 

 

【布局文件源码】

<?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="match_parent"
    android:orientation="horizontal"
    android:paddingBottom="20dp"
    android:paddingTop="20dp" >

    <com.itheima.news_listview.view.MyImageView
        android:scaleType="fitXY"
        android:background="#ff0000"
        android:id="@+id/item_img_icon"
        android:layout_width="68dp"
        android:layout_height="68dp"
        android:layout_gravity="center"
        android:layout_marginRight="10dp"
        android:src="@drawable/ic_launcher" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/item_tv_title"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="3dp"
            android:singleLine="true"
            android:text="title"
            android:textColor="#000000"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/item_tv_des"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:maxLines="2"
            android:text="des"
            android:textColor="#666666"
            android:textSize="13sp" />

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center" >

            <TextView
                android:id="@+id/item_tv_comment"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:text="comment"
                android:textColor="#000000"
                android:textSize="13sp" />

            <TextView
                android:layout_marginRight="10dp"
                android:id="@+id/item_tv_type"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:text="娱乐"
                android:textColor="#666666"
                android:textSize="13sp" />
        </RelativeLayout>
    </LinearLayout>

</LinearLayout>

  

 

posted @ 2017-10-23 20:58  OzTaking  阅读(352)  评论(0)    收藏  举报