当前位置:   article > 正文

android安卓看点新闻课设

android安卓看点新闻课设

一、系统需求分析

1.1 引言

1.1.1 开发目的

看点新闻App的开发是为了实时查看最新消息以了解社会动态,增长知识,增广见闻,顺便娱乐一下内心世界来放松自己。

1.1.2 开发背景

随着新媒体的崛起,纸媒遭受到重大打击,纸媒发展之路愈走愈窄,面临着前所未有的挑战。由于互联网的发展,人们获得信息的来源越来越多。为了满足人们对信息的渴望追求,各种类型的新闻App层出不穷,新闻App凭借其丰富的资讯资源,实时的信息推送和方便的社交互动被越来越多的用户认可。其具有许多报纸所没有的优势,它所提供的新闻信息打破了读报所需的线性时间和空间模式,慢慢改变了受众对世界的认识习惯。因此,开发一个新闻App显得尤其重要!

1.2 项目概述

1.2.1 产品功能描述

看点新闻App是基于Android Studio编辑器上开发的一款可以查看、添加、删除新闻,登录,编辑个人资料,查看个人收藏,清除缓存的安卓App。

1.2.2 运行环境

   操作系统:Window10
   开发工具:Android Studio 3.4.1
   数据库:LitePal,mysql
   硬件环境:
  • 1
  • 2
  • 3
  • 4

CPU:Intel® Core™i5-7200U CPU @ 2.50GHz 2.71 GHz
内存:12.0GB

1.3 系统功能描述

1.3.1 基本描述

看点新闻App通过获取互联网专业数据科技服务商—聚合数据的新闻接口来实现新闻数据的展示。由于每日限制100次请求,故每次请求时就缓存新闻数据到本地数据库中。当每次下拉刷新就分页查询10条新闻数据重新显示在对应的tab碎片中。用户可以根据自己的兴趣点击对应的tab标签来阅读新闻,清除本地缓存,登录后(取消)收藏新闻,查看个人收藏,添加、查看、删除个人发布的文章等。

1.3.2 系统功能描述

登录、注册模块:注册过的用户登录后才能(取消)收藏新闻,查看个人收藏,添加、查看、删除个人发布的文章等。
个人信息模块:用户登录后可以查看、修改个人资料。
个人文章模块:用户登录后可以发布、查看、删除文章。
个人收藏模块:用户登录后可以(取消)收藏新闻接口数据子项,并且查看自己收藏的所有新闻。
清除缓存模块:该功能主要清除浏览网页时在本地留下的离线内容和图片缓存。
展示新闻列表模块:该功能主要在用户打开App时,就请求聚合数据提供的新闻接口来显示在tab页面并将请求的数据缓存到本地数据库中。若当日请求次数已用完,则分页查询本地数据库。

二、系统总体设计

2.1 系统整体结构

系统结构图
在这里插入图片描述

2.2 数据存储设计

用户表:
字段名 数据类型 长度 是否为null 字段描述
userAccount varchar 20 否 账号
nickname varchar 20 是 昵称
userPwd varchar 20 否 登录密码
userSex varchar 6 是 性别
userBirthDay varchar 20 是 生日
userSignature varchar 50 是 个性签名
imagePath varchar 50 是 保存头像的路径
新闻表:
字段名 数据类型 长度 是否为null 字段描述
reason varchar 20 否 数据响应理由
result varchar 20 否 结果集
stat int 4 否 响应状态
uniquekey varchar 100 否 新闻id
title varchar 100 否 新闻标题
date varchar 50 否 请求日期
category varchar 10 否 新闻标签
author_name varchar 30 否 新闻作者
url varchar 200 否 新闻链接
thumbnail_pic_s varchar 200 否 附图1的地址
thumbnail_pic_s02 varchar 200 否 附图2的地址
thumbnail_pic_s03 varchar 200 否 附图3的地址
新闻收藏表:
字段名 数据类型 长度 是否为null 字段描述
userIdNumer varchar 20 否 用户账号
newsId varchar 100 否 新闻id
newSTitle varchar 100 否 新闻标题
newsUrl varchar 200 否 新闻链接
个人文章表:
字段名 数据类型 长度 是否为null 字段描述
userId varchar 20 否 用户账号
articleTitle Varchar 50 否 文章标题
articleAuthor varchar 20 否 用户昵称
articleTime varchar 50 否 发布时间
articleImagePath varchar 100 是 文章图片地址
articleContent varchar 100 否 文章内容

三、系统详细设计

3.1 登录、注册功能

(1) 用户第一次启动App时,可以查看新闻列表和具体的新闻内容,但是不能查看和编辑个人资料,(取消)收藏一条新闻内容,查看个人收藏和我的文章等。只有用户登录后才可实现这些被限制的功能。
(2) 当用户没有账号时,他可以选择注册并登录使用。注册过程中,因为LitePal数据库底层已内置了一个索引,所以我将用户账号设置为唯一标识的字段。若有用户输入相同的账号,系统将提醒用户重新输入账号。当输入密码和确认密码相同即可注册成功!注意,以上所有输入均不为空。

3.2 编辑资料功能

用户登录后点击编辑资料时,其根据需要修改对应的信息后,点击左上角的返回按钮,再点击主界面的抽屉弹出按钮,即可看到刚才修改的个人信息。

3.3 个人收藏功能

用户登录后在主界面新闻列表中点击某个新闻子项后进入webview展示新闻内容,点击右下角的收藏按钮即可进行收藏,再次点击则取消收藏!回到主界面后,点击左上角抽屉按钮弹出导航,点击个人收藏即可看到刚才收藏的新闻标题。

3.4 文章管理功能

用户登录后在主界面点击左上角的按钮,弹出抽屉导航栏,点击”我的文章”即可查看自己发布的新闻列表,点击右下角的悬浮按钮即可进入编辑文章的界面。在编辑文章界面输入文章标题和内容,同时可以添加显示文章的一张图片。点击发布按钮之后返回到“我的文章”界面即可看到刚才添加的文章!点击某个卡片即可查看该文章的具体内容。在文章详情界面,可以点击红色垃圾箱按钮删除该文章!

3.5 清除缓存功能

用户点击某个新闻子项进入浏览时,新闻内容和图片将会缓存到本地,此时用户可以在抽屉导航中点击“清除缓存”即可清除本地缓存。

四、系统实现

4.1 登录、注册功能

在这里插入图片描述

在这里插入图片描述

4.2 编辑资料功能

在这里插入图片描述
在这里插入图片描述

4.3 个人收藏功能

在这里插入图片描述
在这里插入图片描述

4.4 文章管理功能

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.5 清除缓存功能

在这里插入图片描述
在这里插入图片描述

4.6 部分主要代码

4.6.1异步消息处理机制来填充新闻列表

private void getDataFromNet(final String data) {
    @SuppressLint("StaticFieldLeak")
    AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
        //子线程
        @Override //储备key:547ee75ef186fc55a8f015e38dcfdb9a
        protected String doInBackground(Void... params) { // 自己的key:af2d37d2ed31f7a074f1d49b5460a0b5,可以替换下面请求中的key
            String path = "http://v.juhe.cn/toutiao/index?type=" + data + "&key=af2d37d2ed31f7a074f1d49b5460a0b5";
            URL url = null;
            try {
                url = new URL(path);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                //设置请求方式
                connection.setRequestMethod("GET");
                //设置读取超时的毫秒数
                connection.setReadTimeout(5000);
                //设置连接超时时间
                connection.setConnectTimeout(5000);
                //获取状态码
                int responseCode = connection.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK) { // 200
                    //获取服务器返回的输入流
                    InputStream inputStream = connection.getInputStream();
                    String json = streamToString(inputStream, "utf-8");
                    //返回任务的执行结果
                    return json;
                } else {
                    //返回的状态码不是200
                    System.out.println(responseCode);
                    return 404 + data;
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (ProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return 404 + data;
        }
//当给后台任务执行完毕并通过return语句返回时,此方法将被调用,返回来的数据可以进行一些UI操作,并将处理的参数传入
        protected void onPostExecute(final String result) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //查看状态码是否为200,若不是(开子线程),然后从本地加载相应的数据
                    NewsBean newsBean = null;
                    //不包括endIndex
                    Log.d("后台处理的数据为:", "run: " + result);
                    if (!result.substring(0, 3).equals("404")) {
                        newsBean = new Gson().fromJson(result, NewsBean.class);
                        System.out.println(newsBean.getError_code());
                        if ("0".equals("" + newsBean.getError_code())) {
                            //obtainmessage()方法是从消息池中拿来一个msg,不需要另开辟空间new,new需要重新申请,效率低,obtianmessage可以循环利用;
                            Message msg = newsHandler.obtainMessage();
                            msg.what = UPNEWS_INSERT;
                            msg.obj = newsBean;
                            //发送一个通知来填充数据,因为安卓不允许在子线程中进行UI操作
                            newsHandler.sendMessage(msg);
                        } else {
                            //{"resultcode":"112","reason":"超过每日可允许请求次数!","result":null,"error_code":10012}
                            //实现从数据库加载数据
                            Log.d("超过请求次数或者其他原因", "run: 现在从本地数据库中获取");
                            Log.d("当前tab名字为:", "run: " + currentTabName);
                            threadLoaderData(currentTabName);
                        }
                    } else {
                        threadLoaderData(result.substring(3));
                    }
                }
            }).start();
        }

        //当后台任务中调用了publishProgress(Progress...)方法后,onProgressUpdate方法很快被执行
        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);
        }
    };
    //启动异步加载任务
    task.execute();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81

4.6.2加载数据,实现从本地数据库中读取数据刷新到newsListView的适配器中,其中用到了分页查询和多线程

private void threadLoaderData(final String category) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                //沉睡1.5s,本地刷新很快,以防看不到刷新效果
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //若快速点击tab,则会出现getActivity()为空的情况,但是第一次加载肯定不会出错,所以将要拦截,以防app崩溃
            if (getActivity() == null)
                return;
            //此处的用法:runOnUiThread必须是在主线程中调用,getActivity()获取主线程所在的活动,切换子线程到主线程
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    //重新生成数据,传入tab条目
                    loaderRefreshData(category);
                    //表示刷新事件结束,并隐藏刷新进度条
                    swipeRefreshLayout.setRefreshing(false);
                }
            });
        }
    }).start();
}
private void loaderRefreshData(final String category) {
    //top,shehui,guonei,guoji,yule,tiyu,junshi,keji,caijing,shishang
    String categoryName = "头条";
    if (category.equals("top")) {
        categoryName = "头条";
    } else if (category.equals("shehui")) {
        categoryName = "社会";
    } else if (category.equals("guonei")) {
        categoryName = "国内";
    } else if (category.equals("guoji")) {
        categoryName = "国际";
    } else if (category.equals("yule")) {
        categoryName = "娱乐";
    } else if (category.equals("tiyu")) {
        categoryName = "体育";
    } else if (category.equals("junshi")) {
        categoryName = "军事";
    } else if (category.equals("keji")) {
        categoryName = "科技";
    } else if (category.equals("caijing")) {
        categoryName = "财经";
    } else if (category.equals("shishang")) {
        categoryName = "时尚";
    }
    //页数加1
    ++pageNo;
    List<NewsBean.ResultBean.DataBean> dataBeanList = new ArrayList<>();
    NewsBean.ResultBean.DataBean bean = null;
    int offsetV = (pageNo - 1) * pageSize;
    Log.d("pageNo", "页数为: " + pageNo);
    Log.d("offsetV", "偏移量为: " + offsetV);
    Log.d("offsetV", "以下开始查询");
    List<NewsInfoBean> beanList = LitePal.where("category = ?", categoryName).limit(pageSize).offset(offsetV).find(NewsInfoBean.class);
    Log.d("TAG", "查询的数量为:" + beanList.size());
    //若查询的结果为0,则重新定位页数为1
    if (beanList.size() == 0) {
        pageNo = 1;
        offsetV = (pageNo - 1) * pageSize;
        beanList = LitePal.where("category = ?", categoryName).limit(pageSize).offset(offsetV).find(NewsInfoBean.class);
        Log.d("分页查询", "loaderRefreshData: 已经超过最大页数,归零并重新查询!");
    }
    Log.d("刷新查到的数据大小", "run: " + beanList.size());
    for (int i = 0, len = beanList.size(); i < len; ++i) {
        bean = new NewsBean.ResultBean.DataBean();
        bean.setDataBean(beanList.get(i));
        dataBeanList.add(bean);
        Log.d("刷新id:", "run: " + beanList.get(i));
    }
    contentItems = dataBeanList;
    //将dataBeanList赋值给全局的contentItems,否则点击新闻子项会出错,并且contentItems之前要清空,不然起不到更新视图的作用
    TabAdapter adapter = new TabAdapter(getActivity(), contentItems);
    newsListView.setAdapter(adapter);
    //当adapter中的数据被更改后必须马上调用notifyDataSetChanged予以更新。
    adapter.notifyDataSetChanged();
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82

五、联系与交流

q:969060742 完整代码、报告、apk
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/586837
推荐阅读
相关标签
  

闽ICP备14008679号