新闻网络版

来源:互联网 发布:迪杰斯特拉算法 动画 编辑:程序博客网 时间:2024/06/10 05:05


一、---框架---



首先还是来把总体的编码流程来树梳理一下,按照这个顺序来编码可以使思路更加清晰。

(1)创建两个View,一个listview一个item_view

(2)根据view的id来找到listview

(3)从数据库获得数据

<1>创建一个包含News数据信息的bean,bean中包含image、title、url和content等

<2>有了news的bean就应该有操作bean的Utils,这里创建一个NewsUtils类

<3>NewsUtils的作用就是获取新闻数据的,里面主要有两个方法:getAllNewsForNetWork和getAllNewsForDatabase

<4>网络那个后面说,从数据库中得到首先要有数据库和他的操作类,创建NewsOpenHelper和NewsDaoUtils

<5>NewsOpenHelper是数据库的帮助类,NewsDaoUtils中定义增删改查的方法

<6>流程是NewsUtils.getAllNewsForDatabase()->NewsDaoUtils.getNews()

(4)将数据传给item_view并做显示

<1>通过上面的步骤得到ArrayList<NewsBean>类型的新闻数据,下面是在ListView中展示了

<2>ListView使用要通过一个Adapter类,我们定义一个NewsAdapter类并实现其四个覆写BaseAdapter的四个方法

<3>在NewsAdapter中的getView()中将我们定义好的item_view布局并将其转换成一个view,并根据面得到的数据来给view

的各个件赋值

(5)从网络端获取数据,并将数据库中的数据更新

<1>上面也提到了,通过网络获取数据,在NewsUtils中定义getAllNewsForNewWork

<2>也就是通过网络访问服务器中GetNewsServlet,实现输入流和输出流的对接,当然这边是输入流了

<3>将得到的流通过StreamUtils.streamToString()转化成字符串

<4>因为数据是json格式的,所以需要先转化成json对象再进行解析,最终编程ArrayList

<5>注意在返回数据之前,先将数据库清空,然后将数据缓存到里边

<6>回到主函数,因为主线程中不能处理时间过长的时间,所以要建立一个子线程获取网络数据

<7>建立一个主线程来进行ListView的展示

(6)当有事件点击时的跳转

<1>当有点击事件时,跳转到news_url

(7)smartimageview 的原理 

<1>自定义了一个MyImageview类继承了Imageview,添加三个构造方法

<2>添加一个setImageUrl方法接受一个图片url

<3>新建一个子线程去请求url获取图片资源

<4>将获取的图片Bitmap通过handler发送给主线程,主线程设置给当前view

<5>在布局中引用MyImageview,需要指定完成的包名路径。



二、---ListView布局---



Activity中就只有一个ListView就不展示了,下面是 item_news_layout.xml 的代码

使用线性和相对布局相结合的方式了就行布局,包括标题、内容、图片和评论等
<?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.iigt.Internews.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>



三、---获得数据库数据---



(1)创建一个包含News数据信息的bean,bean中包含image、title、url和content等
package com.iigt.Internews.bean;public class NewsBean {public String title;public String des;public String news_url;public int id;public int comment;public int type;public String time;public String icon_url;}

(2)有了news的bean就应该有操作bean的Utils,这里创建一个NewsUtils类
package com.iigt.Internews.utils;public class NewsUtils {public static String newsPath_url = "http://115.25.200.156:8080/itheima74/servlet/GetNewsServlet";//封装新闻的假数据到list中返回public static ArrayList<NewsBean> getAllNewsForNetWork(Context context) //从数据库中获取上次缓存的新闻数据做listview的展示public static ArrayList<NewsBean> getAllNewsForDatabase(Context context) }

(3)NewsUtils的作用就是获取新闻数据的,里面主要有两个方法:getAllNewsForNetWork和getAllNewsForDatabase
//从数据库中获取上次缓存的新闻数据做listview的展示public static ArrayList<NewsBean> getAllNewsForDatabase(Context context) {return new NewsDaoUtils(context).getNews();}

(4)网络那个后面说,从数据库中得到首先要有数据库和他的操作类,创建NewsOpenHelper和NewsDaoUtils
package com.iigt.Internews.dao;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteDatabase.CursorFactory;import android.database.sqlite.SQLiteOpenHelper;public class NewsOpenHelper extends SQLiteOpenHelper {public NewsOpenHelper(Context context) {super(context, "heimanews1", null, 1);}@Overridepublic void onCreate(SQLiteDatabase db) {/*newsJson.put("id", newsBean.getId());newsJson.put("title", newsBean.getTitle());newsJson.put("des", newsBean.getDes());newsJson.put("icon_url", newsBean.getIcon_url());newsJson.put("news_url", newsBean.getNews_url());newsJson.put("type", newsBean.getType());newsJson.put("time", newsBean.getTime());newsJson.put("comment", newsBean.getComment());*/db.execSQL("create table news (_id integer  ,title varchar(200),des varchar(300),icon_url varchar(200),news_url varchar(200)," +" type integer , time varchar(100),comment integer)");}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {// TODO Auto-generated method stub}}

(5)NewsOpenHelper是数据库的帮助类,NewsDaoUtils中定义增删改查的方法
package com.iigt.Internews.dao;import java.util.ArrayList;import com.iigt.Internews.bean.NewsBean;import android.content.ContentValues;import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;public class NewsDaoUtils {private NewsOpenHelper newsOpenHelper;public NewsDaoUtils(Context context){//创建一个帮助类对象newsOpenHelper = new NewsOpenHelper(context);}//删除数据库中缓存的旧数据public void delete(){//通过帮助类对象获取一个数据库操作对象SQLiteDatabase db = newsOpenHelper.getReadableDatabase();db.delete("news", null, null);db.close();}//向数据库中添加新闻数据public void saveNews(ArrayList<NewsBean> list){//通过帮助类对象获取一个数据库操作对象SQLiteDatabase db = newsOpenHelper.getReadableDatabase();for (NewsBean newsBean : list) {ContentValues values = new ContentValues();values.put("_id", newsBean.id);values.put("title", newsBean.title);values.put("des", newsBean.des);values.put("icon_url", newsBean.icon_url);values.put("news_url", newsBean.news_url);values.put("type", newsBean.type);values.put("time", newsBean.time);values.put("comment", newsBean.comment);db.insert("news", null, values);}db.close();}//从数据库中获取缓存的新闻数据public ArrayList<NewsBean> getNews(){ArrayList<NewsBean> list = new ArrayList<NewsBean>();//通过帮助类对象获取一个数据库操作对象SQLiteDatabase db = newsOpenHelper.getReadableDatabase();Cursor cursor = db.rawQuery("select * from news", null);//查询获取数据if(cursor != null && cursor.getCount() > 0){while(cursor.moveToNext()){NewsBean newsBean = new NewsBean();newsBean. id = cursor.getInt(0);newsBean. title = cursor.getString(1);newsBean. des =cursor.getString(2);newsBean. icon_url =cursor.getString(3);newsBean. news_url =cursor.getString(4);newsBean. type = cursor.getInt(5);newsBean. time =cursor.getString(6);newsBean. comment = cursor.getInt(7);list.add(newsBean);}}db.close();cursor.close();return list;}}
其获取数据的流程是NewsUtils.getAllNewsForDatabase()->NewsDaoUtils.getNews()



四、---数据控件显示---




(1)通过上面的步骤得到ArrayList<NewsBean>类型的新闻数据,下面是在ListView中展示了
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mContext = this;lv_news = (ListView) findViewById(R.id.lv_news);//1.先去数据库中获取缓存的新闻数据展示到listviewArrayList<NewsBean> allnews_database = NewsUtils.getAllNewsForDatabase(mContext);if(allnews_database !=null && allnews_database.size()>0){//创建一个adapter设置给listviewNewsAdapter newsAdapter = new NewsAdapter(mContext, allnews_database);lv_news.setAdapter(newsAdapter);}

(2)ListView使用要通过一个Adapter类,我们定义一个NewsAdapter类并实现其四个覆写BaseAdapter的四个方法
package com.iigt.Internews.adapter;import java.util.ArrayList;import com.iigt.Internews.R;import com.iigt.Internews.bean.NewsBean;import com.iigt.Internews.view.MyImageView;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.TextView;public class NewsAdapter extends BaseAdapter {private ArrayList<NewsBean> list;private Context context;//通过构造方法接受要显示的新闻数据集合public NewsAdapter(Context context,ArrayList<NewsBean> list){this.list = list;this.context = context;}@Overridepublic int getCount() {return list.size();}@Overridepublic Object getItem(int position) {return list.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {View view = null;//1.复用converView优化listview,创建一个view作为getview的返回值用来显示一个条目if(convertView != null){view = convertView;}else {//context:上下文, resource:要转换成view对象的layout的id, root:将layout用root(ViewGroup)包一层作为codify的返回值,一般传null//view = View.inflate(context, R.layout.item_news_layout, null);//将一个布局文件转换成一个view对象//通过LayoutInflater将布局转换成view对象//view =  LayoutInflater.from(context).inflate(R.layout.item_news_layout, null);//通过context获取系统服务得到一个LayoutInflater,通过LayoutInflater将一个布局转换为view对象LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);view = layoutInflater.inflate(R.layout.item_news_layout, null);}//2.获取view上的子控件对象MyImageView item_img_icon = (MyImageView) view.findViewById(R.id.item_img_icon);TextView item_tv_des = (TextView) view.findViewById(R.id.item_tv_des);TextView item_tv_title = (TextView) view.findViewById(R.id.item_tv_title);TextView item_tv_comment = (TextView) view.findViewById(R.id.item_tv_comment);TextView item_tv_type = (TextView) view.findViewById(R.id.item_tv_type);//3.获取postion位置条目对应的list集合中的新闻数据,Bean对象NewsBean newsBean = list.get(position);//4.将数据设置给这些子控件做显示item_img_icon.setImageUrl(newsBean.icon_url);item_tv_title.setText(newsBean.title);item_tv_des.setText(newsBean.des);item_tv_comment.setText("评论:"+newsBean.comment);//0 :头条 1 :娱乐 2.体育switch (newsBean.type) {case 0:item_tv_type.setText("头条");break;case 1:item_tv_type.setText("娱乐 ");break;case 2:item_tv_type.setText("体育");break;default:break;}return view;}}
在NewsAdapter中的getView()中将我们定义好的item_view布局并将其转换成一个view,并根据面得到的数据来给view

的各个件赋值



五、---网络获取数据---




(1)上面也提到了,通过网络获取数据,在NewsUtils中定义getAllNewsForNewWork
public static String newsPath_url = "http://115.25.200.156:8080/itheima74/servlet/GetNewsServlet";//封装新闻的假数据到list中返回public static ArrayList<NewsBean> getAllNewsForNetWork(Context context) {ArrayList<NewsBean> arrayList = new ArrayList<NewsBean>();try{//1.请求服务器获取新闻数据//获取一个url对象,通过url对象得到一个urlconnnection对象URL url = new URL(newsPath_url);HttpURLConnection connection = (HttpURLConnection) url.openConnection();//设置连接的方式和超时时间connection.setRequestMethod("GET");connection.setConnectTimeout(10*1000);//获取请求响应码int code = connection.getResponseCode();if(code == 200){//获取请求到的流信息InputStream inputStream = connection.getInputStream();//将流转换成字符串String result = StreamUtils.streamToString(inputStream);//2.解析获取的新闻数据到List集合中。JSONObject root_json = new JSONObject(result);//将一个字符串封装成一个json对象。JSONArray jsonArray = root_json.getJSONArray("newss");//获取root_json中的newss作为jsonArray对象for (int i = 0 ;i < jsonArray.length();i++){//循环遍历jsonArrayJSONObject news_json = jsonArray.getJSONObject(i);//获取一条新闻的jsonNewsBean newsBean = new NewsBean();newsBean. id = news_json.getInt("id");newsBean. comment = news_json.getInt("comment");//评论数newsBean. type = news_json.getInt("type");//新闻的类型,0 :头条 1 :娱乐 2.体育newsBean. time = news_json.getString("time");newsBean. des = news_json.getString("des");newsBean. title = news_json.getString("title");newsBean. news_url = news_json.getString("news_url");newsBean. icon_url = news_json.getString("icon_url");arrayList.add(newsBean);}//3.清除数据库中旧的数据,将新的数据缓存到数据库中new NewsDaoUtils(context).delete();new NewsDaoUtils(context).saveNews(arrayList);}}catch (Exception e) {e.printStackTrace();}return arrayList;}

(2)也就是通过网络访问服务器中GetNewsServlet,实现输入流和输出流的对接,当然这边是输入流了
package com.itheima.service;import java.io.IOException;import java.sql.*;import java.util.ArrayList;public class GetNewsServlet extends HttpServlet {// 构造方法public GetNewsServlet() {super();}// 摧毁这个servlet,不太懂public void destroy() {super.destroy(); // Just puts "destroy" string in log// Put your code here}public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {try{ArrayList<NewsBean> news = NewsDao.getNews();JSONArray jsonArray = new JSONArray();for (NewsBean newsBean : news) {JSONObject newsJson = new JSONObject();newsJson.put("id", newsBean.getId());newsJson.put("title", newsBean.getTitle());newsJson.put("des", newsBean.getDes());newsJson.put("icon_url", newsBean.getIcon_url());newsJson.put("news_url", newsBean.getNews_url());newsJson.put("type", newsBean.getType());newsJson.put("time", newsBean.getTime());newsJson.put("comment", newsBean.getComment());jsonArray.put(newsJson);}JSONObject allNewsJson = new JSONObject();allNewsJson.put("newss", jsonArray);response.getOutputStream().write(allNewsJson.toString().getBytes("gbk"));}catch (Exception e) {}}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}public void init() throws ServletException {}}

(3)将得到的流通过StreamUtils.streamToString()转化成字符串
public class StreamUtils {public static String streamToString(InputStream  in){String result ="";try{//创建一个字节数组写入流ByteArrayOutputStream out = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int length = 0;while (  (length =  in.read(buffer)) !=-1) {out.write(buffer, 0, length);out.flush();}result =   new String(out.toByteArray(),"gbk");//result = out.toString();//将字节流转换成stringout.close();}catch (Exception e) {e.printStackTrace();}return result;}}
因为数据是json格式的,所以需要先转化成json对象再进行解析,最终编程ArrayList

(5)注意在返回数据之前,先将数据库清空,然后将数据缓存到里边
//3.清除数据库中旧的数据,将新的数据缓存到数据库中new NewsDaoUtils(context).delete();new NewsDaoUtils(context).saveNews(arrayList);

(6)回到主函数,因为主线程中不能处理时间过长的时间,所以要建立一个子线程获取网络数据
//2.通过网络获取服务器上的新闻数据用list封装 ,获取网络数据需要在子线程中做new Thread(new Runnable() {@Overridepublic void run() {//请求网络数据ArrayList<NewsBean> allNews = NewsUtils.getAllNewsForNetWork(mContext);//通过handler将msg发送到主线程去更新UiMessage msg = Message.obtain();msg.obj = allNews;handler.sendMessage(msg);}}).start();

(7)建立一个主线程来进行ListView的展示
private Handler handler = new Handler(){public void handleMessage(android.os.Message msg) {ArrayList<NewsBean> allNews = (ArrayList<NewsBean>) msg.obj;if(allNews != null && allNews .size()>0){//3.创建一个adapter设置给listviewNewsAdapter newsAdapter = new NewsAdapter(mContext, allNews);lv_news.setAdapter(newsAdapter);}};};



六、---点击事件---



点击事件处理函数
public void onItemClick(AdapterView<?> parent, View view, int position,long id) {//需要获取条目上bean对象中url做跳转NewsBean bean = (NewsBean) parent.getItemAtPosition(position);String url = bean.news_url;//跳转浏览器Intent intent = new Intent();intent.setAction(Intent.ACTION_VIEW);intent.setData(Uri.parse(url));startActivity(intent);}

如下是自定义的从网络上获取图片的方法
public class MyImageView extends ImageView {public MyImageView(Context context) {super(context);}public MyImageView(Context context, AttributeSet attrs) {super(context, attrs);}public MyImageView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}private Handler handler = new Handler(){public void handleMessage(android.os.Message msg) {Bitmap bitmap = (Bitmap) msg.obj;MyImageView.this.setImageBitmap(bitmap);};};public void setImageUrl(final String url_str){new Thread(new Runnable() {@Overridepublic void run() {try{//获取url对应的图片资源,bitmapURL url = new URL(url_str);HttpURLConnection openConnection = (HttpURLConnection) url.openConnection();openConnection.setRequestMethod("GET");openConnection.setConnectTimeout(10*1000);int code = openConnection.getResponseCode();if(code == 200){InputStream inputStream = openConnection.getInputStream();Bitmap bitmap = BitmapFactory.decodeStream(inputStream);Message msg = Message.obtain();msg.obj = bitmap;handler.sendMessage(msg);}}catch (Exception e) {e.printStackTrace();}}}).start();}}

最后新闻的展示界面如下





1 0
原创粉丝点击