Android新闻客户端案例开发

bzog7779 9年前

来自: http://blog.csdn.net/sdksdk0/article/details/50752686


  新闻客户端,顾名思义就是看新闻用的客户端。

  该新闻用到的知识模块有:android高级界面设计(FragmentViewPager),android网络通信(http通信),开源组件(xutils框架-HttpUtils模块、xutils框架-BitmapUtils模块),开源框架(library)。所需jar包:xUtilsgsonandroid-support-v4。

 主界面滑动标签:library框架用于主界面标签
主界面ViewPagerViewPager与上部分的library框架结合做成Fragment动态效果
ListView中的每个Item


HttpUtils模块进行是用于进行访问网络,获取json数据
BitmapUtils模块进行网络图片的加载和显示
android-support-v4.jar包提供ViewPager控件
library开源代码框架库,是用来实现简易新闻客户端上端的滑动标签,同时它与ViewPager控件结合最终实现的是Fragment的动态实现。
简易新闻客户端上端滑动标签是用了library开源代码框架中的com.viewpagerindicator.TabPageIndicator控件
ViewPager控件是android-support-v4.jar包中的android.support.v4.view.ViewPager控件。
用了com.viewpagerindicator.TabPageIndicator这个控件之后,要对界面主题(Theme)进行修改,在styles.xml文件中创建相关的style


首先导入libary库:千万不要直接把库拷贝进项目文件夹中,这样可能会出现各种其他不知名的错误,建议通过Import Module方式一步步导入库文件。然后在file->project structure->dependencies->3Model dependency中选择library库就可以了,还要在2中导入一个gson.jar和xUtils.jar。此时库已成功导入。


我们首先来写布局文件,activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"                  xmlns:tools="http://schemas.android.com/tools"                  android:layout_width="match_parent"                  android:layout_height="match_parent"      >        <include          android:id="@+id/header"          android:layout_width="match_parent"          android:layout_height="@dimen/header_height"          layout="@layout/header"/>        <com.viewpagerindicator.TabPageIndicator          android:id="@+id/indicator"          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:layout_below="@+id/header">      </com.viewpagerindicator.TabPageIndicator>        <android.support.v4.view.ViewPager          android:id="@+id/viewpager"          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:layout_below="@+id/indicator">      </android.support.v4.view.ViewPager>  </RelativeLayout>


第2个是头部header.xml

<?xml version="1.0" encoding="utf-8"?>  <RelativeLayout      xmlns:android="http://schemas.android.com/apk/res/android"      android:layout_width="match_parent"      android:layout_height="@dimen/header_height"      android:background="@mipmap/setting_iv_bg"      android:gravity="center">        <TextView          android:text="@string/header_text"          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:textSize="@dimen/header_text_size"          />  </RelativeLayout>

第三个是下面的viepage页面,fragment.xml

<?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/newsList"          android:layout_width="match_parent"          android:layout_height="wrap_content"></ListView>        </LinearLayout>

以及细节部分fragment_list_item.xml

<?xml version="1.0" encoding="utf-8"?>  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"      android:layout_width="match_parent"      android:layout_height="match_parent"      >            <ImageView           android:id="@+id/newIcon"          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:layout_alignParentLeft="true"          android:src="@mipmap/skyblue_logo_whatsapp_checked"/>            <LinearLayout           android:orientation="vertical"          android:layout_width="wrap_content"          android:layout_height="wrap_content"          android:layout_alignParentRight="true"          android:layout_toRightOf="@+id/newIcon"          >                    <TextView          android:id="@+id/newTitle"          android:layout_width="wrap_content"          android:layout_height="wrap_content"          style="@style/newTitleTxtSize"            />          <TextView               android:id="@+id/newTime"              android:layout_width="wrap_content"              android:layout_height="wrap_content"              style="@style/newTimeTxtSize"              />                </LinearLayout>    </RelativeLayout>

既然是一个新闻客户端那必须要有数据,那么数据当然就需要json解析来从第三方网站获取新闻数据,下面来简要介绍一下json数据的解析过程。

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它基于ECMAScript的一个子集。JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C、C++、C#、Java、JavaScript、Perl、Python等)。这些特性使JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成(一般用于提升网络传输速率)。


这个时候我们需要在src中新建一个bean类来存放json的数据

public class jsonBean {      private String title;      private String url;      private String listimage;      private String pubdate;      public String getTitle() {          return title;      }      public void setTitle(String title) {          this.title = title;      }      public String getUrl() {          return url;      }      public void setUrl(String url) {          this.url = url;      }      public String getListimage() {          return listimage;      }      public void setListimage(String listimage) {          this.listimage = listimage;      }      public String getPubdate() {          return pubdate;      }      public void setPubdate(String pubdate) {          this.pubdate = pubdate;      }  }

然后再bean中再创建一个ListBean.java,用于存取多个新闻的内容,这里面需要两个内部类,通过data获取NewsList,然后通过NewsLis获取到NewsItem中的值。

public class listBean {      //变量名最好跟json中一样      public NewsList data;        public static class NewsList{          //变量名最好跟json中一样          public ArrayList<NewsItem> news;      }        public static class NewsItem{          public String title;          public String url;          public String listimage;          public String pubdate;      }}

接下来就需要访问网络了,新建一个utils包,再建一个NetUtils.java类

public class NetUtils {        //定义我们需要的变量        private HttpUtils httpUtils;        //全局变量        private Gson gson=new Gson();        private List<News> newsList=new ArrayList<News>();          private News news;          //获取新闻信息        public List<News> getNews(String url){           //访问网络是一个耗时操作,建议开启新线程           GetNewsRunnable getNewsRunnable=new GetNewsRunnable(httpUtils, gson, newsList, news, url);           getNewsRunnable.run();           return newsList;        }          public void addAll(List<News> newsList){           this.newsList.addAll(newsList);        }     }
新建一个GetNewsRunnable.java,请求网络。
 
public class GetNewsRunnable implements Runnable{       private HttpUtils httpUtils;     private Gson gson;     private List<News> newsList;     private News news;     private String url;     private NetUtils netUtils;       public GetNewsRunnable(HttpUtils httpUtils,Gson gson,List<News> newsList,News news,String url){        this.httpUtils=httpUtils;        this.gson=gson;        this.newsList=newsList;        this.news=news;        this.url=url;        netUtils=new NetUtils();     }       //run方法中访问网络并解析json数据     public void run() {        if(newsList==null){           newsList=new ArrayList<News>();        }        httpUtils=new HttpUtils();          httpUtils.send(HttpMethod.GET, url, new RequestCallBack<String>() {             public void onFailure(HttpException arg0, String arg1) {              Log.e("failure", "访问失败");           }             public void onSuccess(ResponseInfo<String> responseInfo) {              Log.e("success", "访问成功");              //访问成功,就进行数据解析              NewsListBean newsListBean=gson.fromJson(responseInfo.result, NewsListBean.class);              //for-each循环              for(NewsListBean.NewsItem newsItem:newsListBean.data.news){                 news=new News();                 news.setTitle(newsItem.title);                 news.setListimage(newsItem.listimage);                 news.setUrl(newsItem.url);                 news.setPubdate(newsItem.pubdate);                 newsList.add(news);                 netUtils.addAll(newsList);              }           }        });     }  }
好了,我们现在需要添加一个适配器了,4个构造方法getCount()、getItem、getItemId、getView可以自动生成就可以了,在适配器中我们首先把变量写好

//定义变量  private List<News> newsList;  private LayoutInflater mInflater;  //获取外部布局用的  private BitmapUtils mBitmapUtils;  //加载和显示图片用的
public NewsListAdapter(Context context,List<News> newsList){      this.newsList=newsList;      this.mInflater=LayoutInflater.from(context);      mBitmapUtils=new BitmapUtils(context);  }

//真正存放东西的方法  @Override  public View getView(int position, View convertView, ViewGroup parent) {      // TODO Auto-generated method stub  ViewHolder holder=null;      if(convertView==null){//如果传进来的view为空,就进行创建,并填充内容          holder=new ViewHolder();          convertView=mInflater.inflate(R.layout.fragment_list_item, null);          holder.newIcon=(ImageView) convertView.findViewById(R.id.newIcon);          holder.newTime=(TextView) convertView.findViewById(R.id.newTime);          holder.newTitle=(TextView) convertView.findViewById(R.id.newTitle);          convertView.setTag(holder);      }else{          holder=(ViewHolder) convertView.getTag();      }      //将数据放到我们的控件当中      News news=newsList.get(position);      holder.newTitle.setText(news.getTitle());      holder.newTime.setText(news.getPubdate());      mBitmapUtils.display(holder.newIcon, news.getListimage());      return convertView;  }  //模拟我们传递的控件  class ViewHolder{      ImageView newIcon;      TextView newTitle;      TextView newTime;  }    //把所有News加进List中  public void addListItem(List<News> list){      newsList.addAll(list);

通过适配器将数据传送到listview中,之后我们要用到fragment,

//这里是ListView的滚动和点击事件  newsList.setOnItemClickListener(new OnItemClickListener() {     @Override     public void onItemClick(AdapterView<?> arg0, View arg1, int position,                       long arg3) {        // TODO Auto-generated method stub  //获取新闻详细信息的地址        String descriptionUrl=newsDatas.get(position).getUrl();        //定义并实例化Intent        Intent intent=new Intent(getActivity().getApplicationContext(),DescriptActivity.class);        String name="url";        //将值放到intent当中        intent.putExtra(name, descriptionUrl);        //开启Activity        startActivity(intent);     }  });
然后我们添加一些详情页TabIndicatorAdapter

最后描述新闻详情

public class DescriptActivity extends Activity {         private WebView newsDescription;       @Override     protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_descript);          String url=this.getIntent().getExtras().get("url").toString();        newsDescription=(WebView) findViewById(R.id.newsDescription);          /**  * 适配屏幕  */  newsDescription.getSettings().setUseWideViewPort(true);        newsDescription.getSettings().setLoadWithOverviewMode(true);        newsDescription.setVerticalScrollBarEnabled(true);        newsDescription.setHorizontalScrollBarEnabled(false);        newsDescription.loadUrl(url);       }  }
记得在清单文件中添加网络权限等,还有一些步骤就不一一细说了,具体的可以下载源码看一下。

<uses-permission android:name="android.permission.INTERNET" />
最终效果图为:

点击打开链接

源码下载地址:点击打开链接http://download.csdn.net/detail/sdksdk0/9446330