------------------------------------------------------------------------
今天做详情页以及列表的刷新,今天做完之后算暂时把最初版本的学校资讯给做完了
惯例,先上效果图
PS:那个𠇔的图片是因为我们学校有个校领导叫X𠇔X的名字,结果维护官网的同学可能是图简单就直接切了个图丢进去,命名又没命名好,我想了一两个小时都没想出来怎么筛选跳过他,没办法了,只能下次跟上面提意见看看能不能改改了
就从简单的说起吧,首先是列表刷新,这个刷新之前在新建页面的时候已经把SwipeRefreshLayout丢进去了,所以只要在Activity里初始化,写好逻辑代码就行了
那么需要增加的是一个标志,代表是否是第一次加载数据,因为每次加载数据的方法都写在getJsoupContent()里了,我们没必要再写一个和这个差不多的方法,直接加个标志进去,判断一下,最后得出结果然后返回一个不一样的msg就行了
private boolean ifFirstInitData=true;
那么还要多加个msg
private final int REFRESH=0x02;
以及对应的handler判断和adapter的刷新以及refresh标志的取消(不取消标志难道一直让他在那打转?笑)
caseREFRESH:
adapter.notifyDataSetChanged();
Toast.makeText(getContext(),"刷新成功",Toast.LENGTH_SHORT).show();
schoolSwipeRefreshLayout.setRefreshing(false);break;
然后在联网获取数据的方法getJsoupContent()加个if来判断标志位,决定到底发送哪条msg
if(ifFirstInitData){
ifFirstInitData=false;
handler.sendEmptyMessage(INITRECYLERVIEW);
}else{
handler.sendEmptyMessage(REFRESH);
}
最后是全部代码
SchoolInfoFragmActivity.java
public class SchoolInfoFragmActivity extendsFragment {private ListschoolInfoList;private final int GETJSOUPCONTENT=0x00,INITRECYLERVIEW=0x01,REFRESH=0x02;privateSwipeRefreshLayout schoolSwipeRefreshLayout;privateSchoolInfoListAdapter adapter;privateRecyclerView schoolRecyclerView;private boolean ifFirstInitData=true;private Handler handler = newHandler(){
@Overridepublic voidhandleMessage(Message msg) {super.handleMessage(msg);switch(msg.what){caseGETJSOUPCONTENT:newThread(runnable).start();break;caseINITRECYLERVIEW:
adapter= newSchoolInfoListAdapter(getContext(),schoolInfoList,schoolRecyclerView);
adapter.setOnItemClickListener(newSchoolInfoListAdapter.OnItemClickListener() {
@Overridepublic void onItemClick(View view, intposition) {//Log.e("onitemclickTag", schoolInfoList.get(position).getTitle());
Intent intent = new Intent(getContext(),SchoolDateilActivity.class);
intent.putExtra("dateilUrl",schoolInfoList.get(position).getPageUrl());
startActivity(intent);
}
});
schoolRecyclerView.setAdapter(adapter);break;caseREFRESH:
adapter.notifyDataSetChanged();
Toast.makeText(getContext(),"刷新成功",Toast.LENGTH_SHORT).show();
schoolSwipeRefreshLayout.setRefreshing(false);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);
schoolSwipeRefreshLayout.setOnRefreshListener(newSwipeRefreshLayout.OnRefreshListener() {
@Overridepublic voidonRefresh() {
handler.sendEmptyMessage(GETJSOUPCONTENT);
}
});
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(){
schoolInfoList= new ArrayList<>();
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 );
}if(ifFirstInitData){
ifFirstInitData=false;
handler.sendEmptyMessage(INITRECYLERVIEW);
}else{
handler.sendEmptyMessage(REFRESH);
}
}
}
那么刷新就解决了
接下来完成一下这个详情页
这里说到两个开源框架,一个是banner,主要是做图片轮播的框架,另外一个就比较常用了,glide图片加载框架,嘛,这个的话之前就说了要用框架来加载图片,只不过是想再自己做一遍加载再复习一下过程而已,那么现在开始就用框架来实现这个功能了
首先是添加依赖,然后sync一下,这国际惯例了
//banner图片轮播依赖
compile 'com.youth.banner:banner:1.4.9'
//glide图片加载依赖
compile "com.github.bumptech.glide:glide:3.7.0"
那么详情页,首先得有个页,有个layout
activity_dateil.xml
插句话,其实中间那个设置了背景的View可要可不要,之所以加只是为了在没有图片的时候有个过渡,直接空白的然后突然闪一张图片出来,感觉视觉效果不好吧
然后是做个glideImageLoder,当然了,banner的实现不一定要glide,但是必须得有个玩意来加载图片吧,那么得封装一下
GlideImageLoader.java
public class GlideImageLoader extendsImageLoader {
@Overridepublic voiddisplayImage(Context context, Object path, ImageView imageView) {//具体方法内容自己去选择,次方法是为了减少banner过多的依赖第三方包,所以将这个权限开放给使用者去选择
Glide.with(context.getApplicationContext())
.load(path)
.crossFade()
.into(imageView);
}
}
然后就直接把这个详情页对应的Activity写完就行了
public class SchoolDateilActivity extendsBaseActivity {privateString dateilUrl,detailContent;private List dateilImgUrl = new ArrayList();privateSpanned contentsp;privateTextView detailTitleTv,detailTimeTv,detailContentTv;privateBanner banner;privateString detailTitleString,detailTimeString;private final int GETDETAILDATA=0x00,PUTVIEWSDATA=0X01;private Handler handler = newHandler(){
@Overridepublic voidhandleMessage(Message msg) {super.handleMessage(msg);switch(msg.what){caseGETDETAILDATA:newThread(deailDataRunnable).start();break;casePUTVIEWSDATA:
putViewsData();
initBanner();
detailTitleTv.setText(detailTitleString);
detailTimeTv.setText(detailTimeString);break;
}
}
};
@Overrideprotected voidinitVariablesAndService() {//获取详情页链接
dateilUrl = getIntent().getExtras().get("dateilUrl").toString();
handler.sendEmptyMessage(GETDETAILDATA);
}
@Overrideprotected voidinitViews(Bundle savedInstanceState) {
setContentView(R.layout.activity_dateil);
detailTitleTv=(TextView) findViewById(R.id.detail_title);
detailTimeTv=(TextView) findViewById(R.id.detail_time);
detailContentTv=(TextView) findViewById(R.id.detail_content);
banner=(Banner) findViewById(R.id.detail_image);
}
Runnable deailDataRunnable= newRunnable() {
@Overridepublic voidrun() {
getDetailData();
}
};/*** 获取详情页所需数据*/
private voidgetDetailData(){
Connection conn=Jsoup.connect(dateilUrl);//修改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();
}
detailTitleString= doc.select("[class=listpicabs_text_title]").text();
detailTimeString= doc.select("[class=listpicabs_text_info]").text();
detailTimeString= detailTimeString.substring(6,16);
Elements detailImgUrlEles= doc.select("[class=listpicabs_text_show]").select("img");
Element element= doc.select("span").first();
doc.select("img").remove();for(Element et:detailImgUrlEles){
dateilImgUrl.add(et.absUrl("src"));
Log.e("detailimg", et.absUrl("src"));
}
Log.e("ttag", element.toString());
detailContent=element.toString();while(detailContent.indexOf("
")!=-1){
detailContent= detailContent.replace("
","
");
}
detailContent= detailContent.replace("。
","。
");if (android.os.Build.VERSION.SDK_INT >=android.os.Build.VERSION_CODES.N) {
contentsp=Html.fromHtml(detailContent,Html.FROM_HTML_MODE_LEGACY);
}else{
contentsp=Html.fromHtml(detailContent);
}
handler.sendEmptyMessage(PUTVIEWSDATA);
}private voidputViewsData(){
detailContentTv.setText(contentsp);
}/*** 初始化Banner轮播*/
private voidinitBanner(){//设置图片加载器
banner.setImageLoader(newGlideImageLoader());//设置图片集合
banner.setImages(dateilImgUrl);//banner设置方法全部调用完毕时最后调用
banner.start();
}
}
这里可以看到banner和glide的使用方法都非常简单,glide自不用说,很多开发者都在用,banner的话,从这个initBanner方法中也可以看出,最简单的使用只需要在页面里设置个banner控件,然后在Activity代码里初始化,然后设置对应的图片加载方法类,然后设置图片的url,再start就完事了
那么今天也就做到这,后面的应该进度会比较快,因为很多功能都是我之前在这个项目前身的寻呼都实现好了的,往里面加就是了,在这些都做完之后,我也还得优化一下,把能够重用的都封装一下