Android小项目——新闻APP

前言:

 在公司学习了一段时间Android知识,决定做一个小项目,目的是学会运用所学的基础知识,在这里记录一下开发历程,大家可以把它看成一款入门级练手的 Demo 应用吧~

项目概述:

类型:

新闻APP(低仿今日头条)

基本功能:

欢迎页面加载(3s,点击可跳过)——Activity相关

用户注册/登录 ——SQLite运用

横向滑动列表显示新闻类别——TabLayout、ViewPager、FragmentPagerAdapter的应用

底部菜单栏 切换——Fragment运用

–-主页(显示新闻列表)——ListView

–-设置(退出应用、退出登录、清空缓存)——Activity管理、SharePreference

–-我的(账号安全、新闻收藏夹)——SQLite

新闻列表下拉、上滑实现刷新——自定义ListView

逐条收藏新闻、删除新闻——SharePreference

仿UI界面——各类控件运用

点击查看新闻详情 —— WebView

用户界面更换头像功能——Android运行时权限、多媒体、Content Provider

 

源码及下载地址:

https://download.csdn.net/download/qq_34149526/10977199

PS:

最近有不少朋友反馈程序闪退问题,我查看了一下,是因为我采用的数据接口(天行数据)请求下来的数据中,图片链接的数据为空(之前一直是正常数据),导致解析图片时空指针异常,最终程序闪退。json数据如下:

{"code": 200,"msg": "success","newslist": [{"ctime": "2019-07-18 00:00","title": "空间科学卫星:迈向空间科学强国","description": "新华科技","picUrl": "",--------------->此处为空!!!"url": "http:\/\/www.xinhuanet.com\/tech\/2019-07\/18\/c_1124767044.htm"},……
}

修改方法一:替换含有图片数据接口,可采用聚合数据等(使用自行百度),注意修改代码中的数据字段名!!!

修改方法二:在代码中解析图片的地方加上非空校验,程序不会崩溃,但是新闻列表中不会显示图片。

修改方法三:自行想办法解决~哈哈

下面简单贴一下修改方法二://针对以下几个类做非空校验,希望大家以我为鉴,养成良好编码习惯。1、MyBitmapUtils.java:
public Bitmap getBitmap(String url) {if(TextUtils.isEmpty(url)){return null;}Bitmap bitmap;……
}
2、HttpUtils.java:
public static Bitmap decodeUriAsBitmapFromNet(String imgUrl) {if(TextUtils.isEmpty(imgUrl)){return null;}URL fileUrl = null;Bitmap bitmap = null;……
}
3、NewsAdapter.java:
@Override
public View getView(int position, View convertView, ViewGroup parent) {……if(news.getNews_img()!=null) {viewHolder.newsImg.setImageBitmap(news.getNews_img());}……
}
4、NetCacheUtils.java:
private Bitmap downLoadBitmap(String url) {……} finally {if (conn != null) {conn.disconnect();}}……}

        关于界面无法显示内容,原因是我申请的天行数据的API接口调用次数已用完(当时我是有10万次的免费调用次数,不得不感叹你们的强大),具体解决方法是更换TechFragment、MiliFragment、SportFragment、EnteFragment四个类里面的url地址,原地址已无法正常请求数据。可以自己去天行数据申请免费接口,替换即可(具体url格式参考天行数据官方文档,我已经很久不用它了)。

在这里我再贴出一位评论区小伙伴 “qq_41835735”给出的解决方案,给大家一个参考。

----------华丽分割线----------

下面进入重点,开始介绍这个项目

1、项目结构:

类文件:

资源文件:

2、主要功能及其代码实现:

欢迎页面:(持续时间为3s);

利用handler机制并开启一个线程,实现展示欢迎页面3s后页面跳转;

 final Message message = new Message();final Thread thread = new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(3000);message.what = 1;handler.sendMessage(message);} catch (InterruptedException e) {e.printStackTrace();}}});

欢迎页面加载完毕后会判断是否有用户登录,若没有用户登录,会跳转到注册&登录页面

final Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);if (msg.what == 1) {//判断用户是否登录boolean userIsLogin = (boolean) SharedPreUtil.getParam(WelcomeActivity.this,SharedPreUtil.IS_LOGIN, false);if (userIsLogin) {Intent intent = new Intent(WelcomeActivity.this, MainActivity.class);startActivity(intent);} else {Intent intent = new Intent(WelcomeActivity.this, LoginOrRegisterActivity.class);startActivity(intent);}finish();} else if (msg.what == 0) {thread.interrupt();}}};

 注册或登录页面:

             

 “注册”和“登陆”功能的实现主要是应用的SQLite数据库存储技术;

注册——存

SQLiteDatabase db = dbHelper.getWritableDatabase();String username_str = username.getText().toString();String userpassword_str = userpassword.getText().toString();String repassword_str = repassword.getText().toString();if (userpassword_str.equals(repassword_str)) {ContentValues values = new ContentValues();//组装数据values.put("name", username_str);values.put("password", userpassword_str);db.insert("User", null, values);startActivity(new Intent(RegisterActivity.this, LoginActivity.class));finish();}

登陆——取

 if (cursor.moveToFirst()) {String userpassword_db = cursor.getString(cursor.getColumnIndex("password"));if (userpassword_str.equals(userpassword_db)) {SharedPreUtil.setParam(LoginActivity.this, SharedPreUtil.IS_LOGIN, true);SharedPreUtil.setParam(LoginActivity.this, SharedPreUtil.LOGIN_DATA, username_str);//user.setUsername(username_str);//user.setPassword(userpassword_str);Intent intent = new Intent(LoginActivity.this, MainActivity.class);TimeCount.getInstance().setTime(System.currentTimeMillis());startActivity(intent);finish();} else {Toast.makeText(LoginActivity.this, "密码错误,请重新登录", Toast.LENGTH_SHORT).show();}}

另外在实现“注册”中上传头像功能时涉及到一个小知识点——运行时权限;因为要访问图库:

若用户不选择上传,程序会默认使用一个给定好的图片作为用户头像。

@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {switch (requestCode) {case 1:if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {openAlbum();} else {Toast.makeText(this, "You denied the permission", Toast.LENGTH_SHORT).show();}break;}}private void openAlbum() {Intent intent = new Intent("android.intent.action.GET_CONTENT");intent.setType("image/*");startActivityForResult(intent, CHOSSE_PHOTO);}@RequiresApi(api = Build.VERSION_CODES.KITKAT)@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {switch (requestCode) {case CHOSSE_PHOTO:if (resultCode == -1) {String imgPath = AlbumUtil.handleImageOnKitKat(this, data);setHead(imgPath);}break;default:break;}}

用户注册登陆后,即进入主页面:默认为科技新闻,左右滑动即可切换新闻类别;

新闻列表的显示原理及ListView、数据源与Adapter三者相结合,呈现出该画面;

    final String url = "http://api.tianapi.com/keji/?key=7d829a4176fef4ad7409c2dc129905ed&num=30";private View view;private LoadListView mListView;private List<News> newsList;private NewsAdapter adapter;

其中数据源的获取涉及到了HTTPClient的GET请求网络资源以及解析json数据的相关知识;

 JSONObject jsonObject = new JSONObject(jsonData);JSONArray jsonArray = jsonObject.getJSONArray("newslist");for (int i = 0; i < 10; i++) {JSONObject json_news = jsonArray.getJSONObject(i);String imgUrl = json_news.getString("picUrl");/*** 采取三级缓存策略加载图片*/Bitmap bitmap = myBitmapUtils.getBitmap(imgUrl); String title = json_news.getString("title");String date = json_news.getString("ctime");String author_name = json_news.getString("description");String url = json_news.getString("url");Log.d(TAG, "url:*-*-*-*-*-*-*" + imgUrl);News news = new News(bitmap, title, url, imgUrl, date, author_name);newsList.add(news);getActivity().runOnUiThread(new Runnable() {@Overridepublic void run() {adapter.notifyDataSetChanged();}});

​​​​该页面同样实现了下拉&上滑刷新新闻的功能:

下拉刷新:

上滑加载: 

该功能具体实现请参考——ListView实现上拉加载&下拉刷新;

删除新闻:

在新闻列表点击每条新闻中的×号可完成新闻删除。

 

@Overridepublic void click(View view) {Toast.makeText(getContext(), "该新闻已删除!", Toast.LENGTH_SHORT).show();newsList.remove(Integer.parseInt(view.getTag().toString()));adapter.notifyDataSetChanged();}

为每一个ListView item设置一个鼠标监听器,在remove方法中传入item的索引位置即可完成新闻列表的删除。

 新闻详情页面:(及加载提示)

 

代码实现:

show_news.getSettings().setJavaScriptEnabled(true);Intent intent = getIntent();final String news_url = intent.getStringExtra("url");final String news_title = intent.getStringExtra("title");final String news_date = intent.getStringExtra("date");final String news_author = intent.getStringExtra("author");final String news_picurl = intent.getStringExtra("pic_url");show_news.loadUrl(news_url);

 

获得intent对象中由上一个页面传来的新闻URL,将WebView初始化后进行加载;完成页面详情的展示。

mDialog = new ProgressDialog(ShowNewsActivity.this);mDialog.setMessage("玩命加载ing");show_news.setWebViewClient(new WebViewClient() {//网页加载时的回调@Overridepublic void onPageStarted(WebView view, String url, Bitmap favicon) {super.onPageStarted(view, url, favicon);if (!mDialog.isShowing()) {mDialog.show();}}//网页停止加载时的回调@Overridepublic void onPageFinished(WebView view, String url) {super.onPageFinished(view, url);// 如果没有显示,则显示if (mDialog.isShowing())mDialog.dismiss();}});

实例化ProgressDialog对象,设置标题与提示信息,以对用户进行友好提示。

新闻收藏:

 

代码实现:

主要是利用SQLite存储整个收藏新闻信息;

collect_news.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {collect_news.setImageResource(R.drawable.favorite_selected);SQLiteDatabase db = helper.getWritableDatabase();ContentValues values = new ContentValues();//组装数据values.put("news_url", news_url);values.put("news_title", news_title);values.put("news_date", news_date);values.put("news_author", news_author);values.put("news_picurl", news_picurl);db.insert("Collection_News", null, values);db.close();

设置页面:

清空缓存:

因为在加载新闻列表时对新闻图片采取了三级缓存策略(网络,本地文件,内存),所以会产生一定的缓存,该功能会清理掉所有缓存;

代码实现:

 // 获取文件//Context.getExternalFilesDir() --> SDCard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据//Context.getExternalCacheDir() --> SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据public static long getFolderSize(File file) throws Exception {long size = 0;try {File[] fileList = file.listFiles();for (int i = 0; i < fileList.length; i++) {// 如果下面还有文件if (fileList[i].isDirectory()) {size = size + getFolderSize(fileList[i]);} else {size = size + fileList[i].length();}}} catch (Exception e) {e.printStackTrace();}return size;}/*** * 清除本应用内部缓存(/data/data/com.xxx.xxx/cache) * *** @param context*/public static void cleanInternalCache(Context context) {deleteFilesByDirectory(context.getCacheDir());}

退出应用:

用户点击后直接退出程序并返回桌面。

代码实现:

专门创建了一个用户维护所有活动(页面)的工具类,当用户点击退出按钮时实际调用exit方法,结束活动类表中每一个活动,并执行System.exit(0);退出。

public class ApplicationUtil extends Application {private List<Activity> mList = new LinkedList<Activity>();private static ApplicationUtil instance;private ApplicationUtil() {}public synchronized static ApplicationUtil getInstance() {if (instance == null) {instance = new ApplicationUtil();}return instance;}// 添加Activity到列表中维持public void addActivity(Activity activity) {mList.add(activity);}public void exit() {try {for (Activity activity : mList) {if (activity != null) {activity.finish();}}} catch (Exception e) {e.printStackTrace();} finally {System.exit(0);}}
}

我的:

账号安全:

该功能即修改用户基本信息;本质是对SQLite的应用;

收藏夹:列举曾收藏过的所有新闻;

 

----------华丽分割线----------

 

至此,项目介绍完毕。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/14529.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【编程架构实践】关于技术栈和架构

目录 技术栈和架构 技术栈 1. 项目需求 2. 开发团队技能

提示工程七巧板:让ChatGPT发挥出最佳性能

机器有机器的作用&#xff0c;人有人的独特个性和价值。正因为如此&#xff0c;一方面&#xff0c;ChatGPT 等人工智能语言模型需要通过不断与人类的公共知识信息数据交互、汇聚&#xff0c;不断与人类进行对话&#xff0c;才能拥有越来越好的智能表现&#xff1b;另一方面&…

搭建DVWA渗透测试靶场

目录 一、虚拟机的介绍及安装 二、Windows镜像操作系统安装 三、Windows虚拟机的相关配置 四、DVWA靶场搭建 一、虚拟机的介绍及安装 1、双击运行安装文件&#xff0c;然后一直点下一步 2、我接受 3、勾选增强型&#xff0c;然后继续下一步 4、去掉更新及加入体验计划&a…

用 ChatGPT 实现综艺节目中的“你说我猜”游戏|征稿活动V6

引言&#xff1a;本文为 Cocos 第 6 期社区征稿活动参赛文章&#xff0c;作者「花叔爱折腾」。他用ChatGPT Cocos Creator 做了款 AI 对话的小游戏&#xff0c;以下为开发实录。 前言 在实现这个游戏前&#xff0c;我在思考&#xff0c;GPT 实现的是 AI 对话&#xff0c;我总在…

基于深度强化学习训练《街头霸王·二:冠军特别版》通关关底 BOSS -智能 AI 代理项目上手

文章目录 SFighterAI项目简介实现软件环境项目文件结构 运行指南环境配置验证及调整gym环境&#xff1a; gym-retro 游戏文件夹错误提示及解决Could not initialize NNPACK!错误提示&#xff1a;libGL error: MESA-LOADER: failed to open swrast 运行测试训练模型查看曲线 Tip…

WebGoat8.2.2通关记录一(General、Injection)

安装与部署 # 安装 docker pull webgoat/goatandwolf # 启动 sudo docker run -d -p 6870:8888 -p 6869:8080 -p 6871:9090 webgoat/goatandwolf我下载webgoat版本经常无法自动启动webwolf&#xff0c;需要进入到容器命令函手动启动 docker exec -it -uroot fervent_carson b…

通关pikaqu靶场sql注入数字型(一)

目录 1.数字型注入 2.实战(通过pikachu平台) 3.sql代码原理 1.数字型注入 原理以及步骤和实战 SQL数字型注入是指攻击者通过在SQL语句中注入恶意数字型参数&#xff0c;从而利用程序漏洞获得对数据库的未经授权访问。 实现SQL数字型注入的过程通常包括以下几个步骤&#xff1…

【编程新时代】AI+编程,ChatGPT轻松完成MySql建表CURD操作!

1、向ChatGPT发送指令 你能帮我根据我提供的内容生成mysql建表语句吗&#xff1f;表注释: 学生基础字段:id,guid(varchar255),create_time,create_user_guid,update_time,update_user_guid,delete_time,delete_user_guid业务字段: 名称,性别,年龄要求:1. 表名称根据表注释翻译为…

你不问它不说:ChatGPT 创建的大部分代码都不安全

聚焦源代码安全&#xff0c;网罗国内外最新资讯&#xff01; 编译&#xff1a;代码卫士 ChatGPT 是OpenAI 公司用于聊天机器人的大型语言模型&#xff0c;它生成的代码大部分都是不安全的&#xff0c;而且它虽然能够指出其缺点却无法提醒用户注意代码的不当之处。 就在学术界如…

ChatGPT需要怎样的芯片?

最近&#xff0c;以ChatGPT为首的生成类模型已经成为了人工智能的新热点&#xff0c;硅谷的微软、谷歌等都纷纷大举投资此类技术&#xff08;微软100亿美元入股ChatGPT背后的OpenAI&#xff0c;谷歌也于近日发布了自研的BARD模型&#xff09;&#xff0c;而在中国以百度等为代表…

芯片是如何为ChatGPT提供算力的?怪不得地球都容不下它了

关注公众号&#xff0c;发现CV技术之美 近日&#xff0c;ChatGPT因大规模封号及关闭Plus付费会员的申请引发大家热议。 有网友说这是因为计算资源不够了&#xff0c;已经不单是靠钱能解决得了的问题&#xff0c;地球上已经没有足够的算力来满足ChatGPT的运行需求了。 AI的发展真…

ChatGPT发展报告:原理、技术架构详解和产业未来(附下载)

今年12月1日&#xff0c;OpenAI推出人工智能聊天原型ChatGPT&#xff0c;再次赚足眼球&#xff0c;为AI界引发了类似AIGC让艺术家失业的大讨论。 据报道&#xff0c;ChatGPT在开放试用的短短几天&#xff0c;就吸引了超过 100 万互联网注册用户。并且社交网络流传出各种询问或…

【自然语言处理】【ChatGPT系列】FLAN:微调语言模型是Zero-Shot学习器

FLAN: 微调语言模型是Zero-Shot学习器 《Finetuned Language Models are Zero-shot Learners》 论文地址&#xff1a;https://arxiv.org/abs/2109.01652 相关博客 【自然语言处理】【大模型】BLOOM&#xff1a;一个176B参数且可开放获取的多语言模型 【自然语言处理】【大模型】…

chatglm微调

chatGML 看到 【【官方教程】ChatGLM-6B 微调&#xff1a;P-Tuning&#xff0c;LoRA&#xff0c;Full parameter】 【精准空降到 15:27】 https://www.bilibili.com/video/BV1fd4y1Z7Y5/?share_sourcecopy_web&vd_sourceaa8c13cff97f0454ee41e1f609a655f1&t927 记得看…

ChatGPT微调分类示例

我们将微调 ada 分类器以区分两种运动&#xff1a;棒球和曲棍球。 from sklearn.datasets import fetch_20newsgroups import pandas as pd import openaicategories [rec.sport.baseball, rec.sport.hockey] sports_dataset fetch_20newsgroups(subsettrain, shuffleTrue, …

45个 Cha​tGPT 常用插件说明

45个 ChatGPT 常用插件说明 ChatGPT常用的45个插件&#xff0c;以及它们用途说明&#xff1a; 1/ Slack&#xff1a;查询Slack信息 2/ Zapier&#xff1a;与5000应用&#xff0c;如Google Sheets和Docs进行交互。 3/ Expedia&#xff1a;在一个地方激活你的旅行计划 4/ Kla…

【.Net/C#之ChatGPT开发系列】四、ChatGPT多KEY动态轮询,自动删除无效KEY

ChatGPT是一种基于Token数量计费的语言模型&#xff0c;它可以生成高质量的文本。然而&#xff0c;每个新账号只有一个有限的初始配额&#xff0c;用完后就需要付费才能继续使用。为此&#xff0c;我们可能存在使用多KEY的情况&#xff0c;并在每个KEY达到额度上限后&#xff0…

1.3 - 操作系统 - firewalld防火墙iptables防火墙

「作者简介」:CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「订阅专栏」:此文章已录入专栏《网络安全入门到精通》 Linux防火墙 Frewalld1、常用操作2、开放/关闭服务3、开放/关闭端口4、IP访问端口规则5、安全域Iptables1、常用操作2、四表五链cent…

再见操作系统!ChatGPT和Windows直接在一起了

来源&#xff1a;水木学堂 二十世纪初&#xff0c;微软曾发起过一场“浏览器战争”&#xff0c;用 IE 4.0 成功打赢了浏览器市场份额超过 90% 以上的网景浏览器。当时&#xff0c;微软用的就是“将 IE 放在 Windows 98 ”这样的“禁忌武器”&#xff0c;还因此遭到了日后的反垄…

ChatGPT封杀潮,禁入学校,AI顶会特意改规则,LeCun:要不咱把小模型也禁了?...

2023 点击蓝字 关注我们 关注并星标 从此不迷路 计算机视觉研究院 计算机视觉研究院专栏 作者&#xff1a;Edison_G 狂欢之后&#xff0c;事情的走向开始进入封杀这一过程。 公众号ID&#xff5c;ComputerVisionGzq 学习群&#xff5c;扫码在主页获取加入方式 转自《机器之心》…