android实践练习_android 练习之路 (五)
------------------------------------------------------------------------
之前几天因为竞赛一直没做,得,今天开始接着完成这玩意
上次把架子给搭好了,今天开始就要填内容了,那么我们就从左往右依次做吧
首先是学校资讯界面
还是老规矩,先上效果图
那么可以看到主要是有两个地方有改变,第一个是标题栏随着fragment的切换而改变,第二个就是学校资讯里面有列表以显示学校资讯
首先第一个,很简单,只需要在MainActivity里动动手,每次切换的时候修改标题栏内的textview里的text就行了
protected voidinitViews() {//标题栏标题textview初始化
TitleTv =(TextView) findViewById(R.id.toolbarTitleTv);
fragments.add(SchoolInfoFragmActivity.newInstance());
fragments.add(EventInfoFragmActivity.newInstance());
fragments.add(FriendInfoFragmActivity.newInstance());
fragments.add(UserInfoFragmActivity.newInstance());
showFragment(fragments.get(0));//标题栏内容随fragment切换而改变
TitleTv.setText(TitleString[0]);
initBottomNav();
}
再发一下改完了之后最终的MainActivity吧(因为日子过的久了,这是在竞赛前做完的,不记得是否还有其他改动了)
MainActivity.java
public class MainActivity extendsAppCompatActivity {privateAHBottomNavigation bottomNavigationView;private List fragments = new ArrayList<>();private intcurrentTabIndex;privateTextView TitleTv;private String TitleString[] = {"学校资讯","周边活动","我的好友","我的设置"};
@Overrideprotected voidonCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}protected voidinitViews() {//标题栏标题textview初始化
TitleTv =(TextView) findViewById(R.id.toolbarTitleTv);
fragments.add(SchoolInfoFragmActivity.newInstance());
fragments.add(EventInfoFragmActivity.newInstance());
fragments.add(FriendInfoFragmActivity.newInstance());
fragments.add(UserInfoFragmActivity.newInstance());
showFragment(fragments.get(0));//标题栏内容随fragment切换而改变
TitleTv.setText(TitleString[0]);
initBottomNav();
}private voidinitBottomNav() {
bottomNavigationView=(AHBottomNavigation) findViewById(R.id.bottom_navigation_view);
AHBottomNavigationItem item1= new AHBottomNavigationItem(TitleString[0],
R.drawable.ic_tab_temporary);
AHBottomNavigationItem item2= new AHBottomNavigationItem(TitleString[1],
R.drawable.ic_tab_temporary);
AHBottomNavigationItem item3= new AHBottomNavigationItem(TitleString[2],
R.drawable.ic_tab_temporary);
AHBottomNavigationItem item4= new AHBottomNavigationItem(TitleString[3],
R.drawable.ic_tab_temporary);
bottomNavigationView.addItem(item1);
bottomNavigationView.addItem(item2);
bottomNavigationView.addItem(item3);
bottomNavigationView.addItem(item4);
bottomNavigationView.setColored(false);
bottomNavigationView.setForceTint(false);
bottomNavigationView.setBehaviorTranslationEnabled(true);
bottomNavigationView.setTitleState(AHBottomNavigation.TitleState.ALWAYS_SHOW);
bottomNavigationView.setAccentColor(getResources().getColor(R.color.black_90));
bottomNavigationView.setInactiveColor(getResources().getColor(R.color.nav_text_color_mormal));
bottomNavigationView.setCurrentItem(0);
bottomNavigationView.setDefaultBackgroundColor(
getResources().getColor(R.color.bottom_tab_bar_color));
bottomNavigationView.setOnTabSelectedListener(newAHBottomNavigation.OnTabSelectedListener() {
@Overridepublic boolean onTabSelected(int position, booleanwasSelected) {if (currentTabIndex !=position) {
FragmentTransaction trx=getSupportFragmentManager().beginTransaction();
trx.hide(fragments.get(currentTabIndex));if (!fragments.get(position).isAdded()) {
trx.add(R.id.content, fragments.get(position));
}
trx.show(fragments.get(position)).commit();
TitleTv.setText(TitleString[position]);
}
currentTabIndex=position;return true;
}
});
}private voidshowFragment(Fragment fragment) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content, fragment)
.commit();
}
}
那么到这里,随着fragment的切换修改标题就完事了,很简单,那么接下来做第二个
这个说来话就有点长,简单来说,首先从学校网站上获取信息(我就暂时用我自己学校的吧,也怕乱爬会惹出什么事来),然后后面就简单了,把爬来的内容丢进一个recyclerview里就是了
那么一步一步来吧:
1,从学校官网上获取信息
分两个方面,首先我们肯定要打开学校官网看看前端代码是怎么写的,以便解析,然后获取网站数据,我们就要用到爬虫
首先是学校官网
就不全截取网页了,图太大,截取这部分看看就行了
我们获取的信息就是江科要闻,可以看到江科要闻里有三个红色标题,排在第一位的是一个查询页面,和我们无关,我们就只获取后面的两个红色标题里的内容以及下面的用红色框标注出的黑色标题里的内容
怎么解析一下这个前端代码呢,我们首先查看一下源码,这里我用的是QQ浏览器,在该页面下,选择菜单——工具——开发者工具,打开程序,如下图
别看看起来好像东西不多,等会每个展开够找的了,那么如何快速找到我们需要的内容呢,简单,刚刚不是有标题吗,我们直接把标题复制过来,粘贴到右边的搜索栏里,搜索一下
在这里我们不管右边那些宋体啊,字号之类的东西,这与我们无关,我们只需要知道,在dt标签下,有我们需要的内容,但是仔细一想,这还不够啊,我们一没有图片,二没有该标题对应的链接,这光有一个标题,后续完善recyclerview的时候实现不了功能
但是其实这里已经有链接了,链接就是上面的这个show.php?contentid=23698
其实也很简单,我们自己点击一下那个标题,进入那个标题对应的网页,发现链接是http://www.jxut.edu.cn/show.php?contentid=23698
一对照结果就出来了,那么我们还需要一张图片,图片应该是这个链接里的第一张图,我们用来做列表中的图示
过程就不说了,和这个类似,不过图片有点难搜索,好在网页不大,咱们一个一个点一下,排除法用一下就出来了
那么有了这些素材,我们需要把素材给从网上拿下来,就跟在银行有存款一样,需要用钱的时候也得拿出来再用
这里我们要用到爬虫,本着不重复造轮子的原则,直接用jsoup就行,当然,自己写也是可以的,爬虫并不算复杂,并且我们需要的内容也非常简单
首先添加爬虫依赖
//jsoup爬虫依赖
compile 'org.jsoup:jsoup:1.10.2'
然后我们在SchoolInfoFragmActivity中写这么个方法,使用爬虫获取数据
/*** 使用jsoup获取学校官网数据*/
private voidgetJsoupContent(){
String url= "http://www.jxut.edu.cn/";
Connection conn=Jsoup.connect(url);//修改http包中的header,伪装成浏览器进行抓取
conn.header("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:32.0) Gecko/ 20100101 Firefox/32.0");
Document doc= null;try{
doc=conn.get();
}catch(IOException e) {
e.printStackTrace();
}
Elements elements= doc.select("[class=tabContent blog]");
Elements elements1= elements.select("font");
Elements elements2= elements1.select("a");
Document dt= null;for(Element element : elements2){
String Title=element.text();
String PageUrl= element.attr("abs:href");
Connection ct=Jsoup.connect(PageUrl);
ct.header("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:32.0) Gecko/ 20100101 Firefox/32.0");try{
dt=ct.get();
}catch(IOException e) {
e.printStackTrace();
}
Elements elements3= dt.select("[class=listpicabs_text_show]");
String ImgUrl= "";if(elements3.select("img").first()==null){
}else{
ImgUrl= elements3.select("img").first().absUrl("src");
}
schoolInfoList.add(newSchoolInfo(Title,PageUrl,ImgUrl));
Log.e("mytag", Title);
Log.e("mytag", PageUrl );
Log.e("mytag", ImgUrl );
}
handler.sendEmptyMessage(INITRECYLERVIEW);
}
其实要吐槽的是这个命名并不规范,不应该是这样123命名,很容易造成看不懂,不过后续我应该会再封装,所以这里实现功能就行
至于类似select("font"),attr("abs:href")之类的,都是一些匹配表达式,这里就不赘述了,多了解一下jsoup,或者仔细看看那个网页源码就行了,这里只提一句,我们总不能把所有数据都直接弄下来然后直接使用吧(当然,其实确实是全弄下来了,但是使用的时候总不能动不动就用这一长串吧?),所以要有选择性的筛选一下,这些就相当于筛子
但是这样还是不够的,因为我们不能直接在主线程里使用这个方法,要不然会报异常
所以我们开个线程
Runnable runnable = newRunnable() {
@Overridepublic voidrun() {
getJsoupContent();
}
};
开个线程是可以了,但是什么时候用线程呢,我们用老方法,handler传递一个参数进去
private Handler handler = newHandler(){
@Overridepublic voidhandleMessage(Message msg) {super.handleMessage(msg);switch(msg.what){caseGETJSOUPCONTENT:newThread(runnable).start();break;
}
}
};
至于这个GETJSOUPCONTENT,我们自己定义一个常量来表示就行,不一定说非得是什么什么
private final int GETJSOUPCONTENT=0x00
那么这样就算是基本实现爬取了,跑一下的话,会发现log已经将需要的内容打印出来了(之前在方法里有写log,故而会打印出来,并不是自带log)
E/mytag: 程样国书记为第三十三期入党积极分子讲授第一课
E/mytag: http://www.jxut.edu.cn/show.php?contentid=23698
E/mytag: http://www.jxut.edu.cn/uploadfile/2017/0412/20170412113009539.jpg
E/mytag: 校党委组织青年学子学习省委书记鹿心社南昌大学报告会精神
E/mytag: http://www.jxut.edu.cn/show.php?contentid=23697
E/mytag: http://www.jxut.edu.cn/uploadfile/2017/0412/20170412082735748.jpg
E/mytag: 我校召开课程考核方式改革推进会
E/mytag: http://www.jxut.edu.cn/show.php?contentid=23691
E/mytag: http://www.jxut.edu.cn/uploadfile/2017/0411/20170411102017731.jpg
E/mytag: 胡剑锋强调:提高英语四级通过率要抓好五到位
E/mytag: http://www.jxut.edu.cn/show.php?contentid=23692
E/mytag: http://www.jxut.edu.cn/uploadfile/2017/0411/20170411102846589.jpg
E/mytag: 英国德比大学代表来访我校
E/mytag: http://www.jxut.edu.cn/show.php?contentid=23687
E/mytag: http://www.jxut.edu.cn/uploadfile/2017/0410/20170410055825319.jpg
E/mytag: 我校喜获全省“无偿献血促进奖单位奖”
E/mytag: http://www.jxut.edu.cn/show.php?contentid=23685
E/mytag: http://www.jxut.edu.cn/uploadfile/2017/0410/20170410031942124.jpg
E/mytag: 省卫计委复核我校助产专业
E/mytag: http://www.jxut.edu.cn/show.php?contentid=23672
E/mytag: http://www.jxut.edu.cn/uploadfile/2017/0407/20170407073220317.jpg
E/mytag: 我校第十三届“奋飞蓝天”读书活动月启动
E/mytag: http://www.jxut.edu.cn/show.php?contentid=23670
E/mytag: http://www.jxut.edu.cn/uploadfile/2017/0407/20170407110834662.jpg
E/mytag: 南昌大学张剑教授应邀来校主讲“立德树人”
E/mytag: http://www.jxut.edu.cn/show.php?contentid=23669
E/mytag: http://www.jxut.edu.cn/uploadfile/2017/0407/20170407033431769.jpg
那么到这里,爬取就完事了,但是光有数据还不够,因为我们还必须要做一个recyclerview
首先在布局里给他塞一个recyclerview
activity_school_info_fragm.xml
注意这里是需要添加v7依赖的,印象里之前好像添加过吧,提一句,不再说了
然后我们做一个item的布局
item_school_info.xml
然后我们做recyclerview,我们得要一个adapter
在adapter包下新建一个SchoolInfoListAdapter
这里说一句,其实应该建个基类然后大家一起用,或者说直接写一个通用的adapter的,但是我觉得还是先实现功能再重构吧(好吧,其实是我自己也没太想好后面需要什么样的数据和效果,这样做的话改起来会很费劲,所以先单例模式做效果出来吧)
SchoolInfoListAdapter.java
public class SchoolInfoListAdapter extends RecyclerView.Adapter{private ListschoolInfoList;private LruCachemImageCache;privateContext context;privateRecyclerView recyclerView;static class ViewHolder extendsRecyclerView.ViewHolder{
TextView schoolInfoTitle;
ImageView schoolInfoImg;publicViewHolder(View view){super(view);
schoolInfoTitle=(TextView) view.findViewById(R.id.item_title);
schoolInfoImg=(ImageView) view.findViewById(R.id.item_image);
}
}public SchoolInfoListAdapter(Context context,Listlist,RecyclerView recyclerView){this.context =context;this.schoolInfoList =list;this.recyclerView =recyclerView;int maxCache = (int) Runtime.getRuntime().maxMemory();int cacheSize = maxCache / 8;
mImageCache= new LruCache(cacheSize) {
@Overrideprotected intsizeOf(String key, Bitmap value) {returnvalue.getByteCount();
}
};
}
@Overridepublic ViewHolder onCreateViewHolder(ViewGroup parent, intviewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.item_school_info,parent,false);
ViewHolder holder= newViewHolder(view);returnholder;
}
@Overridepublic void onBindViewHolder(ViewHolder holder, intposition) {
holder.setIsRecyclable(false);
SchoolInfo schoolInfo=schoolInfoList.get(position);
holder.schoolInfoTitle.setText(schoolInfo.getTitle());
holder.schoolInfoImg.setTag(schoolInfo.getImgUrl());
Log.e("schoolimgurl", schoolInfo.getImgUrl());
Log.e("tag", position+"");if (mImageCache.get(schoolInfo.getImgUrl()) != null) {
holder.schoolInfoImg.setImageBitmap(mImageCache.get(schoolInfo.getImgUrl()));
}else{
ImageTask it= newImageTask();
it.execute(schoolInfo.getImgUrl());
}
}
@Overridepublic intgetItemCount() {returnschoolInfoList.size();
}class ImageTask extends AsyncTask{privateString imageUrl;
@OverrideprotectedBitmap doInBackground(String... params) {
Bitmap bitmap;if (params[0].equals("")){
bitmap=BitmapFactory.decodeResource(context.getResources(),R.drawable.account_avatar);returnbitmap;
}
imageUrl= params[0];//Log.e("tag", imageUrl);
bitmap =downloadImage();if (mImageCache.get(imageUrl) == null){
mImageCache.put(imageUrl, bitmap);
}//if(bitmap!=null)//Log.e("tag", "notnull");
returnbitmap;
}
@Overrideprotected voidonPostExecute(Bitmap result) {//通过Tag找到ImageView,如果该ImageView所在的item已被移出页面,就会直接返回null//Log.e("tag", "img url is "+imageUrl);
ImageView iv =(ImageView) recyclerView.findViewWithTag(imageUrl);if (iv != null && result != null) {
iv.setImageBitmap(result);//Log.e("tag", "setbitmap");
}
}/*** 根据url从网络上下载图片*/
privateBitmap downloadImage() {
HttpURLConnection con= null;
Bitmap bitmap= null;try{
URL url= newURL(imageUrl);
con=(HttpURLConnection) url.openConnection();
con.setConnectTimeout(5 * 1000);
con.setReadTimeout(10 * 1000);
bitmap=BitmapFactory.decodeStream(con.getInputStream());
}catch(MalformedURLException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}finally{if (con != null) {
con.disconnect();
}
}returnbitmap;
}
}
}
这里说一句
holder.setIsRecyclable(false);
这条语句,如果不加,会出现只能完美加载第一面,也就是进程序之后可视的那些item,至于下面的,不能完美加载,我也不能够完全理解这个问题的产生,但是我清楚这和recyclerview的复用机制有关
当然了,使用其他的框架来进行图片显示以及加载,可以解决这个问题,在这里我之所以用这些比较原始的东西,也是为了更深理解一下recyclerview,后面可能会换成别的框架来实现这个玩意
那么话说回来,在创建adapter的时候,我们需要把数据传输进去
隔了有几天了,不浪费时间,不按顺序写了,直接发最终的样子吧
SchoolInfoFragmActivity.java
public class SchoolInfoFragmActivity extendsFragment {private List schoolInfoList = new ArrayList<>();private final int GETJSOUPCONTENT=0x00,INITRECYLERVIEW=0x01;privateSwipeRefreshLayout schoolSwipeRefreshLayout;privateRecyclerView schoolRecyclerView;private Handler handler = newHandler(){
@Overridepublic voidhandleMessage(Message msg) {super.handleMessage(msg);switch(msg.what){caseGETJSOUPCONTENT:newThread(runnable).start();break;caseINITRECYLERVIEW:
SchoolInfoListAdapter adapter= newSchoolInfoListAdapter(getContext(),schoolInfoList,schoolRecyclerView);
schoolRecyclerView.setAdapter(adapter);break;
}
}
};public staticSchoolInfoFragmActivity newInstance() {return newSchoolInfoFragmActivity();
}
@Nullable
@OverridepublicView onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
handler.sendEmptyMessage(GETJSOUPCONTENT);
View view= inflater.inflate(R.layout.activity_school_info_fragm, container, false);
schoolSwipeRefreshLayout=(SwipeRefreshLayout) view.findViewById(R.id.swipe_refresh_school);
schoolRecyclerView=(RecyclerView) view.findViewById(R.id.recycler_view_school);
LinearLayoutManager layoutManager= newLinearLayoutManager(getActivity());
schoolRecyclerView.setLayoutManager(layoutManager);returnview;
}
Runnable runnable= newRunnable() {
@Overridepublic voidrun() {
getJsoupContent();
}
};/*** 使用jsoup获取学校官网数据*/
private voidgetJsoupContent(){
String url= "http://www.jxut.edu.cn/";
Connection conn=Jsoup.connect(url);//修改http包中的header,伪装成浏览器进行抓取
conn.header("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:32.0) Gecko/ 20100101 Firefox/32.0");
Document doc= null;try{
doc=conn.get();
}catch(IOException e) {
e.printStackTrace();
}
Elements elements= doc.select("[class=tabContent blog]");
Elements elements1= elements.select("font");
Elements elements2= elements1.select("a");
Document dt= null;for(Element element : elements2){
String Title=element.text();
String PageUrl= element.attr("abs:href");
Connection ct=Jsoup.connect(PageUrl);
ct.header("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:32.0) Gecko/ 20100101 Firefox/32.0");try{
dt=ct.get();
}catch(IOException e) {
e.printStackTrace();
}
Elements elements3= dt.select("[class=listpicabs_text_show]");
String ImgUrl= "";if(elements3.select("img").first()==null){
}else{
ImgUrl= elements3.select("img").first().absUrl("src");
}
schoolInfoList.add(newSchoolInfo(Title,PageUrl,ImgUrl));
Log.e("mytag", Title);
Log.e("mytag", PageUrl );
Log.e("mytag", ImgUrl );
}
handler.sendEmptyMessage(INITRECYLERVIEW);
}/*** 加载下拉刷新组件*/
private voidinitSwipeRefreshLayout(){
}
}
那么到这里就实现了图片中的效果了,下一步应该是明天,会实现这个recyclerview的点击效果,效果应该是显示对应item中链接里的内容
android实践练习_android 练习之路 (五)相关推荐
- android实践练习_android 练习之路 (四)
------------------------------------------------------------------------ 今天应该勉强算是把fragment的最基本的框架搭好了 ...
- Android程序员的进阶之路
本文主要论述的是Android程序员的进阶之路,博主本人就是一名android开发攻城狮,所以这里讲述的大多数是android开发攻城狮的技术进阶之路,如有问题请多指正. 大家都知道程序员之中有有菜鸟 ...
- 《Android Studio开发实战》学习(五) - 截图
<Android Studio开发实战>学习(五) - 截图 背景 页面布局 布局文件的编写 代码文件的编写 ImageView控件截图的原理 运行结果 背景 在这里继续学习Android ...
- Hadoop YARN 在快手的应用实践与技术演进之路
本文是房孝敬老师主题为"yarn在快手应用实践与技术演进之路"的分享整理,内容包含yarn系统在快手的应用实践,遇到的问题以及相应的技术演进过程. 讲师介绍:房孝敬,快手大数据架构 ...
- android静默卸载,Android实践 -- Android静默安装和卸载
App的静默安装和卸载 Android系统本身提供了安装卸载功能,但是api接口是@hide的,不是公开的接口,所以在应用级别 是无法实现静默安装和卸载的,要实现静默安装和卸载需要是系统应用,要有系统 ...
- Android 系统(194)---Android实践 -- 设置系统日期时间和时区
Android实践 -- 设置系统日期时间和时区 转自:https://www.cnblogs.com/Free-Thinker/p/6627813.html 设置系统日期时间和时区 设置系统的日期时 ...
- 第50篇 Android Studio实现生命数字游戏(五)计算星座数
第50篇 Android Studio实现生命数字游戏(五)计算星座数 1.变量说明: 1.1.统计圈数 2.计算命数 2.1.使用的数据 2.2.星座对应日期和数字 2.3.说明 2.4.代码 1. ...
- java 设置年轻代堆大小,[JVM学习之路]五堆(一)堆的内存结构参数设置分代思想内存分配...
[JVM学习之路]五堆(一)堆的内存结构参数设置分代思想内存分配 [JVM学习之路]五.堆(一)堆的内存结构.参数设置.分代思想.内存分配策略及TLAB 一.堆的核心概述 堆的特点: 1.一个jvm实 ...
- Android记事本NotePad应用功能拓展(五)
Android记事本NotePad应用功能拓展(五) 一.实现功能 1.夜间模式切换 2.反转时间排序规则 二.项目代码分析 1.夜间模式切换 只要做所有关于界面的地方加上这段代码即可(判断模式设置背 ...
最新文章
- Android SystemProperties系统属性分析
- GridView 激发了未处理的事件“RowEditing”
- oracle主从表分离怎么实时更新数据_高可用数据库主从复制延时的解决方案
- LVM逻辑卷 (概述lvm,管理卷组 物理卷 逻辑卷,磁盘配额)
- 编写properties文件的Eclipse插件
- POJ - 3415 Common Substrings(长度不小于K的公共子串个数)
- jrockit_1.6下载_Oracle JRockit Mission Control 4.1发布
- css3点击会移动到点,CSS3过渡点击事件
- android编程常见问题- Resource ID #0x7f070001 type #0x12 is not valid
- Verilog语言实现并行(循环冗余码)CRC校验
- 为什么要选择基于NAS存储方案
- 从 Oracle 到 PostgreSQL :从 Uptime 到数据库实例运行时间
- 编程的本质--深入理解类型系统/泛型/函数式编程/面向对象编程
- 【老生谈算法】matlab实现信息光学夫琅禾费衍射源码——夫琅禾费衍射
- Boost.Asio使用总结
- 波动率模型:现货、期货及期货期权
- VINS-Mono 论文公式推导与代码解析
- `canvas`破苍穹
- oracle删sequen,sequen是什么意思
- 分隔符中的分页符与分节符
热门文章
- c 语言pets进步天梯题目,2017年9月公共英语一级pets考试样题解析
- 模仿的两端分别是山寨和微创新
- 万人千题 | 九日集训 | 英雄算法联盟合伙人 | 三年之约 | B站直播早起粉丝团
- 深层学习:心智如何超越经验1.1 混乱的时钟
- 家用路由器禁游戏端口_您是否真的需要“游戏”路由器?
- zz十年学会程序设计
- 用Python分析过去10年地震分布~
- linux下防止rm-rf /处理
- java字符转成ncr_NCR字符编码(形如xx)转换为汉字 in JAVA
- 网站攻击+提权基本步骤