Android新闻客户端案列
来源:互联网 发布:淘宝仿真左轮 编辑:程序博客网 时间:2024/04/30 02:06
前言:这是一个仿照网易客户端模仿的简易新闻客户端案例,主要是为了对知识点更深入的了解和整合
1 需求
第一次进入新闻客户端需要请求服务器获取新闻数据,做listview的展示,为了第二次再次打开新闻客户端时能快速显示新闻,需要将数据缓存到数据库中,下次打开可以直接去数据库中获取新闻直接做展示。
2 程序流程
1.写布局listview
2.找到listview,设置条目的点击事件。
3.获取数据提供给listview做展示。 //☆☆☆
4.创建一个Adapter继承BaseAdapter,封装4个方法,需要接收获取的新闻数据
5.将adapter设置给listview。 3
3 用到的知识点
1 Handler机制 2 ListView 3 BaseAdapter(适配器) 4 SqliteOpenHelper 数据库操作 5 自定义组件(MyImageView)
6 数据传输json 等
4 服务器端
用到的jar包 java-json.jar
- <span style="font-size:14px;">package com.itheima.service;
- import java.io.IOException;
- import java.sql.*;
- import java.util.ArrayList;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.json.JSONArray;
- import org.json.JSONObject;
- import com.itheima.service.bean.NewsBean;
- import com.itheima.service.dao.NewsDao;
- public class GetNewsServlet extends HttpServlet {
- public GetNewsServlet() {
- super();
- }
- public void destroy() {
- super.destroy();
- }
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- /*
- 新闻请求路径:
- // http://192.168.1.103:8080/itheima72/servlet/GetNewsServlet
- json格式:
- 用{}包含的是一个JsonObject 用[]包含的是一个JsonArray
- */
- try{
- //从数据库获取新闻数据
- ArrayList<NewsBean> news = NewsDao.getNews();
- //将list中的数据封装成一个jsonArray对象
- 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);
- }
- //将jsonArray对象作为一个json对象,用来返回给客户端
- 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 {
- }
- }</span>
5 Android 客户端
5.1 强新闻数据封装成NewsBean
- <span style="font-size:14px;">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;
- }</span>
5.2 数据库的操作
DAO 层
- <span style="font-size:14px;">package com.example.dao;
- import android.content.Context;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteOpenHelper;
- /**
- * Created by ls on 2016/9/24.
- */
- public class NewsOpenHelper extends SQLiteOpenHelper {
- public NewsOpenHelper(Context context) {
- super(context, "news", null, 1);
- }
- @Override
- public void onCreate(SQLiteDatabase db) {
- db.execSQL("create table news (_id integer primary key ,title varchar(200),des varchar(300),icon_url varchar(200),news_url varchar(200)," +
- " type integer , time varchar(100),comment integer)");
- }
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- }
- }</span>
- <span style="font-family:SimSun;font-size:14px;">package com.example.dao;
- import android.content.ContentValues;
- import android.content.Context;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import com.example.bean.NewsBean;
- import java.util.ArrayList;
- public class NewsDaoUtils {
- private NewsOpenHelper openHelper;
- public NewsDaoUtils(Context context) {
- //创建一个帮助类对象
- openHelper = new NewsOpenHelper(context);
- }
- //删除数据库中缓存的旧数据
- public void delete() {
- //通过帮助类对象获取数据库操作对象
- SQLiteDatabase database = openHelper.getReadableDatabase();
- database.delete("news", null, null);
- database.close();
- }
- //向数据库中添加新闻数据
- public void saveNews(ArrayList<NewsBean> list) {
- //通过帮助类对象获取数据库操作对象
- SQLiteDatabase db = openHelper.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<>();
- //通过帮助类对象获取数据库操作对象
- SQLiteDatabase db = openHelper.getReadableDatabase();
- Cursor cursor = db.rawQuery("select * from news ", null);
- while (cursor.moveToNext()) {
- NewsBean newsBean = new NewsBean();
- //1 根据列名获取列索引
- // newsBean. id = cursor.getInt(cursor.getColumnIndex("_id"));
- //2 根据列的索引直接读取 比如第0列的值
- 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;
- }
- }</span>
5.3 适配器
- <span style="font-size:14px;">package com.example.adapter;
- import android.content.Context;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.TextView;
- import com.example.bean.NewsBean;
- import com.example.newslist.R;
- import com.example.view.MyImageView;
- import java.util.ArrayList;
- public class NewsAdapter extends BaseAdapter {
- Context context;
- ArrayList<NewsBean> list;
- //通过构造方法接收要显示的新闻类数据集合
- public NewsAdapter(Context context) {
- this.context = context;
- }
- public NewsAdapter(Context context, ArrayList<NewsBean> list) {
- this.list = list;
- this.context = context;
- }
- @Override
- public Object getItem(int position) {
- return list.get(position);
- }
- @Override
- public long getItemId(int position) {
- return position;
- }
- @Override
- public int getCount() {
- return list.size();
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- View view = null;
- //1 复用convertView 优化listView ,创建一个view作为getView的返回值,用来显示条目
- if (convertView != null) {
- view =convertView;
- }else{
- //context:上下文 resource:要转换成view对象的layout的id;
- //root:将layout用root(ViewGroup) 作为codify的返回值,一般传null
- //通过LayoutInflater将布局转换成view对象
- // view = LayoutInflater.from(context).inflate(R.layout.item_news_layout, null);
- //通过context获取系统服务得到一个LayoutInflater,通过LayoutInflater将一个布局转换成view对象
- LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- view = inflater.inflate(R.layout.item_news_layout,null);
- }
- //获取view上的子控件对象
- MyImageView myImageView = (MyImageView)view.findViewById(R.id.item_img_icon);
- TextView title = (TextView)view.findViewById(R.id.item_tv_title);
- TextView des = (TextView)view.findViewById(R.id.item_tv_des);
- TextView comment = (TextView)view.findViewById(R.id.item_tv_comment);
- TextView type = (TextView)view.findViewById(R.id.item_tv_type);
- //获取positon位置条目,对应的list集合中的新闻数据,Bean对象
- NewsBean newsBean = list.get(position);
- myImageView.setImageUrl(newsBean.icon_url);
- title.setText(newsBean.title);
- des.setText(newsBean.des);
- comment.setText("评论 :"+newsBean.comment);
- //0头条 1娱乐 2 新闻
- switch (newsBean.type) {
- case 0:
- type.setText("头条");
- break;
- case 1:
- type.setText("娱乐");
- break;
- case 2:
- type.setText("新闻");
- break;
- default:
- break;
- }
- return view;
- }
- }</span>
5.4 请求服务端数据,并封装成List<NewsBean>返回 这一步也是最关键的
中间用到了一个工具类 流转字符串
- <span style="font-size:14px;">package com.example.utils;
- import android.content.Context;
- import com.example.bean.NewsBean;
- import com.example.dao.NewsDaoUtils;
- import org.json.JSONArray;
- import org.json.JSONObject;
- import java.io.InputStream;
- import java.net.HttpURLConnection;
- import java.net.URL;
- import java.util.ArrayList;
- public class NewsUtils {
- public static String newsPath_url = "http://192.168.1.106:8080/itheima74/servlet/GetNewsServlet";
- //封装新闻的假数据到list中返回
- public static ArrayList<NewsBean> getAllNewsForNetWork(Context context) {
- ArrayList<NewsBean> list = new ArrayList<>();
- try {
- //请求服务器获取新闻数据
- URL url = new URL(newsPath_url);
- HttpURLConnection connection = (HttpURLConnection) url.openConnection();
- //设置连接的方式和超时
- connection.setRequestMethod("GET");
- connection.setConnectTimeout(2000);
- //获取请求的响应码
- int code = connection.getResponseCode();
- if (code == 200) {
- //获取请求到的流信息
- InputStream is = connection.getInputStream();
- String result = StreamUtils.stream2String(is);
- //2解析获取的新闻数据到list集合中
- JSONObject jsonObject = new JSONObject(result);//将一个字符串封装成一个json对象
- JSONArray jsonArray = jsonObject.getJSONArray("newss");//获取json_root中newss作为jsonArray对象
- for (int i = 0; i < jsonArray.length(); i++) {//循环遍历新闻array
- JSONObject news_json = jsonArray.getJSONObject(i);//获取一条新闻的json
- NewsBean 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");
- list.add(newsBean); //封装成对象添加到list集合中
- }
- //清楚数据库中的旧的数据,把新的数据缓存到数据库中
- new NewsDaoUtils(context).delete();
- new NewsDaoUtils(context).saveNews(list);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return list;
- }
- //从数据库中获取上次缓存的数据
- public static ArrayList<NewsBean> getAllNewsFromDB(Context context) {
- return new NewsDaoUtils(context).getNews();
- }
- }</span>
- <span style="font-size:14px;">package com.example.utils;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- /**
- * Created by ls on 2016/9/24.
- */
- public class StreamUtils {
- public static String stream2String(InputStream is) {
- //返回一个字节数组写入流
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- byte[] buffer = new byte[1024];
- int size = 0;
- String retValue = "";
- try {
- while ((size = is.read(buffer)) != -1) {
- bos.write(buffer, 0, size);
- }
- retValue = new String(bos.toByteArray(), "gbk");
- } catch (IOException e) {
- e.printStackTrace();
- }
- return retValue;
- }
- }</span>
5.5 自定义处理图片的组件
- <span style="font-size:14px;">package com.example.view;
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.os.Handler;
- import android.os.Message;
- import android.util.AttributeSet;
- import android.widget.ImageView;
- import java.io.InputStream;
- import java.net.HttpURLConnection;
- import java.net.URL;
- /**
- * Created by ls on 2016/9/24.
- * 自定义显示图片的组件
- */
- 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 defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
- private Handler handler = new Handler(){
- @Override
- public void handleMessage(Message msg) {
- Bitmap bitmap =(Bitmap) msg.obj;
- MyImageView.this.setImageBitmap(bitmap);
- }
- };
- public void setImageUrl(final String url_str) {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- URL url = new URL(url_str);
- HttpURLConnection connection = (HttpURLConnection)url.openConnection();
- connection.setRequestMethod("GET");
- connection.setConnectTimeout(2000);
- int code = connection.getResponseCode();
- if (code == 200) {
- InputStream is=connection.getInputStream();
- Bitmap bitmap = BitmapFactory.decodeStream(is);
- Message message = Message.obtain();
- message.obj = bitmap;
- handler.sendMessage(message);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }).start();
- }
- }</span>
5.6 MainActivity
- p<span style="font-size:14px;">ackage com.example.newslist;
- import android.app.Activity;
- import android.content.Context;
- import android.content.Intent;
- import android.net.Uri;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.view.View;
- import android.widget.AdapterView;
- import android.widget.ListView;
- import com.example.adapter.NewsAdapter;
- import com.example.bean.NewsBean;
- import com.example.utils.NewsUtils;
- import java.util.ArrayList;
- public class MainActivity extends Activity implements AdapterView.OnItemClickListener{
- private Context mcontext;
- private ListView listView;
- private Handler handler = new Handler(){
- @Override
- public void handleMessage(Message msg) {
- ArrayList<NewsBean> allnews = (ArrayList<NewsBean>)msg.obj;
- if (allnews != null && allnews.size() > 0) {
- for (NewsBean newsBean: allnews) {
- NewsAdapter adapter = new NewsAdapter(mcontext,allnews);
- listView.setAdapter(adapter);
- }
- }
- }
- };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mcontext = this;
- setContentView(R.layout.activity_main);
- listView = (ListView) findViewById(R.id.listview);
- //1先去数据库中去获取缓存的新闻数据,显示到新闻列表中
- ArrayList<NewsBean> list = NewsUtils.getAllNewsFromDB(mcontext);
- if (list != null && list.size() >0) {
- //创建一个adapter设置给listview
- NewsAdapter adapter = new NewsAdapter(mcontext,list);
- listView.setAdapter(adapter);
- }
- //2通过网络去获取服务器上的新闻数据,用list封装,获取网络数据需要在子线程中去做
- new Thread(new Runnable() {
- @Override
- public void run() {
- //请求网络数据通过
- ArrayList<NewsBean> allnews = NewsUtils.getAllNewsForNetWork(mcontext);
- //通过handler,将数据发送到主线程中去更新
- Message message = Message.obtain();
- message.obj=allnews;
- handler.sendMessage(message);
- }
- }).start();
- //设置listView条目的点击事件
- listView.setOnItemClickListener(this);
- }
- //listview 条目点击时会调用这些方法,parent 代表listview ;view 点击条目上的那个view对象
- // positon 条目的位置 ; id 条目的id
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- //需要获取条目上的bean对象中url做跳转
- NewsBean newsBean = (NewsBean) parent.getItemAtPosition(position);
- String url = newsBean.news_url;
- //跳转到浏览器
- Intent intent = new Intent();
- intent.setAction(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(url));
- startActivity(intent);
- }
- }</span>
6 Layout布局
activity_main.xml
- <span style="font-size:14px;"><?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="vertical">
- <ListView
- android:id="@+id/listview"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- />
- </LinearLayout></span>
行布局 item_news_layout.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:paddingBottom="20dp"
- android:paddingTop="20dp"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal">
- <com.example.view.MyImageView
- android:id="@+id/item_img_icon"
- android:layout_width="60dp"
- android:background="#ff0000"
- android:layout_height="60dp"
- android:scaleType="fitXY"
- android:layout_gravity="center"
- android:src="@drawable/ic_launcher"
- android:layout_marginRight="10dp"
- />
- <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="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="3dp"
- android:singleLine="true"
- android:text="title"
- android:textColor="#000000"
- android:textSize="20sp"
- />
- <TextView
- android:id="@+id/item_tv_des"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="3dp"
- android:maxLines="2"
- android:text="des"
- android:textColor="#666666"
- android:textSize="16sp"
- />
- <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="#666666"
- android:textSize="16sp"
- />
- <TextView
- 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="16sp"
- android:layout_marginRight="10dp"
- />
- </RelativeLayout>
- </LinearLayout>
- </LinearLayout>
7 权限
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
0 1
- Android新闻客户端案列
- Android 新闻客户端开发
- android 新闻客户端开发
- android csdn新闻客户端
- Android 新闻客户端
- Android-新闻客户端
- android之新闻客户端
- Android 新闻客户端
- 新闻客户端android
- Android实践:新闻客户端
- Android 新闻客户端案例
- Android案例《新闻客户端》
- Android简易新闻客户端
- android 仿网易新闻客户端
- Android 新闻客户端学习笔记
- Android 头条新闻客户端
- Android 新闻客户端的学习
- android新闻客户端(一)
- 堆栈内存分配 及 函数返回值问题
- Android M(6.0)以下 ActivityCompat.requestPermissions不会弹框
- 给大家发一个linux下vim的很好用的配置文件
- php正则表达式
- error 与 exception 的区别
- Android新闻客户端案列
- 9.26
- Grid++report的基本设计
- 自定义ViewPager,使其不会左右滑动,解决在最后一页可以往回滑的问题
- 2014 北京区域赛 F Fluorescent HDU5117 (数学+状压+dp)★ ★
- 随心笔记一:JAVA的基本数据类型间转换(一)
- python(二)
- hdu2544 最短路
- 在CentOS系统上安装Eclipse