【0037】Android基础-25-新闻客户端添加网络支持
【1】配置服务器

配置好的服务器可以使用地址:直接访问并返回json数据;
在sqlite软件中执行下面指令:
【指令1】创建数据库

【指令2】创建数据中的表:复制到到命令区,然后执行;
1 -- phpMyAdmin SQL Dump 2 -- http://www.phpmyadmin.net 3 -- 4 -- 生成日期: 2015 年 08 月 08 日 23: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>
浙公网安备 33010602011771号