android小项目之新闻客户端三分析

访客 阅读:267 2021-03-31 23:34:05 评论:0


基于Android的小巫新闻客户端开发--主界面业务逻辑实现

 上一篇介绍了主界面的UI设计,现在直接进入主题,业务逻辑的实现,由于项目的开发总是在不断的完善的,最初实现的效果,总会随项目的进度而做出相应的改变,小巫也不可能从新开发整个客户端,然后再一步一步记录,那没有必要,学习东西,只需要知道关键点在哪里就行了,关于细节方面,遇到再去解决。就是这么简单。

 

主界面的最终实现效果如下;

  

 

下面是MainActivity.java的代码

  1. package com.xiaowu.news;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.HashMap;  
  5. import java.util.List;  
  6.   
  7. import org.json.JSONArray;  
  8. import org.json.JSONObject;  
  9.   
  10. import android.app.Activity;  
  11. import android.content.Intent;  
  12. import android.graphics.Color;  
  13. import android.graphics.drawable.ColorDrawable;  
  14. import android.os.AsyncTask;  
  15. import android.os.Bundle;  
  16. import android.view.Gravity;  
  17. import android.view.KeyEvent;  
  18. import android.view.LayoutInflater;  
  19. import android.view.Menu;  
  20. import android.view.MenuItem;  
  21. import android.view.View;  
  22. import android.view.View.OnClickListener;  
  23. import android.widget.AdapterView;  
  24. import android.widget.AdapterView.OnItemClickListener;  
  25. import android.widget.Button;  
  26. import android.widget.GridView;  
  27. import android.widget.HorizontalScrollView;  
  28. import android.widget.LinearLayout;  
  29. import android.widget.LinearLayout.LayoutParams;  
  30. import android.widget.ListView;  
  31. import android.widget.ProgressBar;  
  32. import android.widget.SimpleAdapter;  
  33. import android.widget.TextView;  
  34. import android.widget.Toast;  
  35.   
  36. import com.xiaowu.news.custom.ConstomSimpleAdapter;  
  37. import com.xiaowu.news.model.Category;  
  38. import com.xiaowu.news.service.SyncHttp;  
  39. import com.xiaowu.news.update.UpdateManager;  
  40. import com.xiaowu.news.util.DensityUtil;  
  41. import com.xiaowu.news.util.StringUtil;  
  42.   
  43. /** 
  44.  *  
  45.  * @author wwj 
  46.  *  
  47.  */  
  48. public class MainActivity extends Activity {  
  49.   
  50.     private final int COLUMNWIDTH_PX = 56;              // GridView每个单元格的宽度(像素)  
  51.     private final int FLINGVELOCITY_PX = 800;           // ViewFilper滑动的距离(像素)  
  52.     private final int NEWSCOUNT = 5;                    // 显示新闻的条数  
  53.     private final int SUCCESS = 0;                      // 加载新闻成功  
  54.     private final int NONEWS = 1;                       // 没有新闻  
  55.     private final int NOMORENEWS = 2;                   // 没有更多新闻  
  56.     private final int LOADERROR = 3;                    // 加载失败  
  57.   
  58.     private long exitTime;                              //按返回键退出的时间  
  59.     private int mColumnWidth_dip;                         
  60.     private int mFlingVelocity_dip;  
  61.     private int mCid;                                   // 新闻编号  
  62.     private String mCategoryTitle;                      // 新闻分类标题  
  63.     private ListView mNewslist;                         // 新闻列表  
  64.     private SimpleAdapter mNewslistAdapter;             // 为新闻内容提供需要显示的列表  
  65.     private ArrayList<HashMap<String, Object>> mNewsData; // 存储新闻信息的数据集合  
  66.     private LayoutInflater mInflater;                   // 用来动态载入没有loadmore_layout界面  
  67.       
  68.     private Button category_Button = null;              // 新闻分类标题栏的向右查看的按钮  
  69.       
  70.     private HorizontalScrollView categoryScrollView = null;// 水平滚动图  
  71.   
  72.     private Button mTitleBarRefresh;                    // 标题栏的刷新按钮  
  73.     private ProgressBar mTitleBarProgress;              // 进度条  
  74.     private Button mLoadmoreButton;                     // 加载更多按钮  
  75.   
  76.     private LoadNewsAsyncTack mLoadNewsAsyncTack;       // 声明LoadNewsAsyncTack引用  
  77.       
  78.   
  79.     @Override  
  80.     public void onCreate(Bundle savedInstanceState) {  
  81.         super.onCreate(savedInstanceState);  
  82.         setContentView(R.layout.news_home_layout);  
  83.           
  84.         //通过id来获取按钮的引用  
  85.         mTitleBarRefresh = (Button) findViewById(R.id.titlebar_refresh);  
  86.         mTitleBarProgress = (ProgressBar) findViewById(R.id.titlebar_progress);  
  87.           
  88.         mTitleBarRefresh.setOnClickListener(loadmoreListener);  
  89.         // 将px转换为dip  
  90.         mColumnWidth_dip = DensityUtil.px2dip(this, COLUMNWIDTH_PX);  
  91.         mFlingVelocity_dip = DensityUtil.px2dip(this, FLINGVELOCITY_PX);  
  92.         //初始化新闻分类的编号  
  93.         mCid = 1;  
  94.         mCategoryTitle = "焦点";  
  95.         mInflater = getLayoutInflater();  
  96.         //存储新闻信息的数据集合  
  97.         mNewsData = new ArrayList<HashMap<String, Object>>();  
  98.         // 获取数组资源  
  99.         String[] categoryArray = getResources().getStringArray(  
  100.                 R.array.categories);  
  101.   
  102.         // 定义一个List数组,用来存放HashMap对象  
  103.         final List<HashMap<String, Category>> categories = new ArrayList<HashMap<String, Category>>();  
  104.         // 分割新闻字符串  
  105.         for (int i = 0; i < categoryArray.length; i++) {  
  106.             String temp[] = categoryArray[i].split("[|]");  
  107.             if (temp.length == 2) {  
  108.                 int cid = StringUtil.string2Int(temp[0]);  
  109.                 String title = temp[1];  
  110.                 Category type = new Category(cid, title);  
  111.                 // 定义一个HashMap对象,用来存放键值对  
  112.                 HashMap<String, Category> hashMap = new HashMap<String, Category>();  
  113.                 hashMap.put("category_title", type);  
  114.                 categories.add(hashMap);  
  115.             }  
  116.         }  
  117.         ConstomSimpleAdapter categoryAdapter = new ConstomSimpleAdapter(this,  
  118.                 categories, R.layout.category_item_layout,  
  119.                 new String[] { "category_title" },  
  120.                 new int[] { R.id.category_title });  
  121.         // 创建一个网格视图, 用于实现新闻标题的布局  
  122.         GridView category = new GridView(this);  
  123.         // 设置单元格的背景色为透明,这样选择分类时就不会显示黄色背景了  
  124.         category.setSelector(new ColorDrawable(Color.TRANSPARENT));  
  125.         // 设置每一个新闻标题的宽度  
  126.         category.setColumnWidth(mColumnWidth_dip);  
  127.         // 设置网格视图的列数  
  128.         category.setNumColumns(GridView.AUTO_FIT);  
  129.         // 设置对齐方式  
  130.         category.setGravity(Gravity.CENTER);  
  131.         // 根据单元格的宽度和数目计算网格视图的宽度  
  132.         int width = mColumnWidth_dip * categories.size();  
  133.         // 获取布局参数  
  134.         LayoutParams params = new LayoutParams(width, LayoutParams.MATCH_PARENT);  
  135.         // 设置参数  
  136.         category.setLayoutParams(params);  
  137.         // 设置Adapter  
  138.         category.setAdapter(categoryAdapter);  
  139.         // 通过ID获取LinearLayout布局对象  
  140.         LinearLayout categoryLayout = (LinearLayout) findViewById(R.id.category_layout);  
  141.         // 将网格视图组件添加到LinearLayout布局当中  
  142.         categoryLayout.addView(category);  
  143.   
  144.         // 添加单元格点击事件  
  145.         category.setOnItemClickListener(new OnItemClickListener() {  
  146.             TextView categoryTitle;  
  147.   
  148.             @Override  
  149.             public void onItemClick(AdapterView<?> parent, View view,  
  150.                     int position, long id) {  
  151.                 // TODO Auto-generated method stub  
  152.                 for (int i = 0; i < parent.getCount(); i++) {  
  153.                     categoryTitle = (TextView) parent.getChildAt(i);  
  154.                     categoryTitle.setTextColor(0XFFADB2AD);  
  155.                     categoryTitle.setBackgroundDrawable(null);  
  156.   
  157.                 }  
  158.                 categoryTitle = (TextView) view;  
  159.                 categoryTitle.setTextColor(0xFFFFFFFF);  
  160.                 categoryTitle  
  161.                         .setBackgroundResource(R.drawable.image_categorybar_item_selected_background);  
  162.                 Toast.makeText(MainActivity.this, categoryTitle.getText(),  
  163.                         Toast.LENGTH_SHORT).show();  
  164.                 //获取新闻分类编号  
  165.                 mCid = categories.get(position).get("category_title").getCid();  
  166.                 mCategoryTitle = categories.get(position).get("category_title").getTitle();  
  167.                 mLoadNewsAsyncTack = new LoadNewsAsyncTack();  
  168.                 mLoadNewsAsyncTack.execute(0true);  
  169.             }  
  170.   
  171.         });  
  172.           
  173.         //第一次获取新闻列表  
  174.         getSpecCatNews(mCid, mNewsData, 0true);  
  175.         // 箭头  
  176.         categoryScrollView = (HorizontalScrollView) findViewById(R.id.categorybar_scrollView);  
  177.         category_Button = (Button) findViewById(R.id.category_arrow_right);  
  178.         category_Button.setOnClickListener(new OnClickListener() {  
  179.   
  180.             @Override  
  181.             public void onClick(View v) {  
  182.                 // TODO Auto-generated method stub  
  183.                 categoryScrollView.fling(mFlingVelocity_dip);  
  184.             }  
  185.         });  
  186.   
  187.         mNewslistAdapter = new SimpleAdapter(this, mNewsData,  
  188.                 R.layout.newslist_item_layout, new String[] {  
  189.                         "newslist_item_title""newslist_item_digest",  
  190.                         "newslist_item_source""newslist_item_ptime" },  
  191.                 new int[] { R.id.newslist_item_title,  
  192.                         R.id.newslist_item_digest, R.id.newslist_item_source,  
  193.                         R.id.newslist_item_ptime });  
  194.         mNewslist = (ListView) findViewById(R.id.news_list);  
  195.           
  196.         View footerView = mInflater.inflate(R.layout.loadmore_layout, null);  
  197.         //在LiseView下面添加“加载更多”  
  198.         mNewslist.addFooterView(footerView);  
  199.         //显示列表  
  200.         mNewslist.setAdapter(mNewslistAdapter);  
  201.           
  202.         mNewslist.setOnItemClickListener(new OnItemClickListener() {  
  203.   
  204.             @Override  
  205.             public void onItemClick(AdapterView<?> parent, View view,  
  206.                     int position, long id) {  
  207.                 // TODO Auto-generated method stub  
  208.                 Intent intent = new Intent(MainActivity.this,  
  209.                         NewsDetailActivity.class);  
  210.                 intent.putExtra("categoryTitle", mCategoryTitle);  
  211.                 intent.putExtra("newsData", mNewsData);  
  212.                 intent.putExtra("position", position);  
  213.                 startActivity(intent);  
  214.             }  
  215.   
  216.         });  
  217.   
  218.         mLoadmoreButton = (Button) findViewById(R.id.loadmore_btn);  
  219.         mLoadmoreButton.setOnClickListener(loadmoreListener);  
  220.           
  221.     }  
  222.   
  223.     /** 
  224.      * 获取指定类型的新闻列表 
  225.      *  
  226.      * @param cid 
  227.      * @return 
  228.      */  
  229.     private int getSpecCatNews(int cid, List<HashMap<String, Object>> newsList,  
  230.             int startnid, boolean firstTime) {  
  231.   
  232.         // 如果是第一次加载的话  
  233.         if (firstTime) {  
  234.             newsList.clear();  
  235.         }  
  236.         //本机:http://10.0.2.2:8080/web/getSpecifyCategoryNews  
  237.         //wifi局域网:192.168.220.1  
  238.         String url = "http://10.0.2.2:8080/web/getSpecifyCategoryNews";  
  239.         String params = "startnid=" + startnid + "&count=" + NEWSCOUNT  
  240.                 + "&cid=" + cid;  
  241.         SyncHttp syncHttp = new SyncHttp();  
  242.   
  243.         try {  
  244.             // 通过Http协议发送Get请求,返回字符串  
  245.             String retStr = syncHttp.httpGet(url, params);  
  246.             JSONObject jsonObject = new JSONObject(retStr);  
  247.             int retCode = jsonObject.getInt("ret");  
  248.             if (retCode == 0) {  
  249.                 JSONObject dataObj = jsonObject.getJSONObject("data");  
  250.                 // 获取返回数目  
  251.                 int totalNum = dataObj.getInt("totalnum");  
  252.                 if (totalNum > 0) {  
  253.                     // 获取返回新闻集合  
  254.                     JSONArray newslistArray = dataObj.getJSONArray("newslist");  
  255.                     // 将用JSON格式解析的数据添加到数据集合当中  
  256.                     for (int i = 0; i < newslistArray.length(); i++) {  
  257.                         JSONObject newsObject = (JSONObject) newslistArray  
  258.                                 .opt(i);  
  259.                         HashMap<String, Object> hashMap = new HashMap<String, Object>();  
  260.                         hashMap.put("nid", newsObject.getInt("nid"));  
  261.                         hashMap.put("newslist_item_title",  
  262.                                 newsObject.getString("title"));  
  263.                         hashMap.put("newslist_item_digest",  
  264.                                 newsObject.getString("digest"));  
  265.                         hashMap.put("newslist_item_source",  
  266.                                 newsObject.getString("source"));  
  267.                         hashMap.put("newslist_item_ptime",  
  268.                                 newsObject.getString("ptime"));  
  269.                         hashMap.put("newslist_item_comments",  
  270.                                 newsObject.getInt("commentcount"));  
  271.                         newsList.add(hashMap);  
  272.                     }  
  273.                     return SUCCESS;  
  274.                 } else {  
  275.                     //第一次加载新闻列表  
  276.                     if (firstTime) {  
  277.                         return NONEWS;          //没有新闻  
  278.                     } else {  
  279.                         return NOMORENEWS;      //没有更多新闻  
  280.                     }  
  281.                 }  
  282.             } else {  
  283.                 return LOADERROR;           //加载新闻失败  
  284.             }  
  285.         } catch (Exception e) {  
  286.             // TODO Auto-generated catch block  
  287.             e.printStackTrace();  
  288.             return LOADERROR;           //加载新闻失败  
  289.         }  
  290.     }  
  291.   
  292.     /** 
  293.      * 为“加载更多”按钮定义匿名内部类 
  294.      */  
  295.     private OnClickListener loadmoreListener = new OnClickListener() {  
  296.   
  297.         @Override  
  298.         public void onClick(View v) {  
  299.             mLoadNewsAsyncTack = new LoadNewsAsyncTack();  
  300.             switch (v.getId()) {  
  301.             //点击加载更多  
  302.             case R.id.loadmore_btn:  
  303.                 mLoadNewsAsyncTack.execute(mNewsData.size(), false);    //不是第一次加载新闻里列表  
  304.                 break;  
  305.             //点击刷新按钮  
  306.             case R.id.titlebar_refresh:  
  307.                 mLoadNewsAsyncTack.execute(0true);  
  308.                 break;  
  309.             }  
  310.         }  
  311.     };  
  312.   
  313.     /** 
  314.      * 异步更新UI 
  315.      * @author wwj 
  316.      * 
  317.      */  
  318.     private class LoadNewsAsyncTack extends AsyncTask<Object, Integer, Integer> {  
  319.   
  320.         //准备运行  
  321.         @Override  
  322.         protected void onPreExecute() {  
  323.             mTitleBarRefresh.setVisibility(View.GONE);  
  324.             mTitleBarProgress.setVisibility(View.VISIBLE);  
  325.             mLoadmoreButton.setText(R.string.loadmore_text);  
  326.         }  
  327.         //在后台运行  
  328.         @Override  
  329.         protected Integer doInBackground(Object... params) {  
  330.             return getSpecCatNews(mCid, mNewsData, (Integer) params[0],  
  331.                     (Boolean) params[1]);  
  332.         }  
  333.         //完成后台任务  
  334.         @Override  
  335.         protected void onPostExecute(Integer result) {  
  336.             switch (result) {  
  337.             //该栏目没有新闻  
  338.             case NONEWS:  
  339.                 Toast.makeText(MainActivity.this, R.string.nonews, Toast.LENGTH_SHORT)  
  340.                         .show();  
  341.                 break;  
  342.             //该栏目没有更多新闻  
  343.             case NOMORENEWS:  
  344.                 Toast.makeText(MainActivity.this, R.string.nomorenews,  
  345.                         Toast.LENGTH_SHORT).show();  
  346.                 break;  
  347.             //加载失败  
  348.             case LOADERROR:  
  349.                 Toast.makeText(MainActivity.this, R.string.loadnewserror, Toast.LENGTH_SHORT)  
  350.                         .show();  
  351.                 break;  
  352.             }  
  353.             mTitleBarRefresh.setVisibility(View.VISIBLE);           //刷新按钮设置为可见  
  354.             mTitleBarProgress.setVisibility(View.GONE);             //进度条设置为不可见  
  355.             mLoadmoreButton.setText(R.string.loadmore_btn);         //按钮信息替换为“加载更多”  
  356.             mNewslistAdapter.notifyDataSetChanged();                //通知ListView更新数据  
  357.         }  
  358.     }  
  359.       
  360.     /** 
  361.      * 添加菜单 
  362.      */  
  363.     @Override  
  364.     public boolean onCreateOptionsMenu(Menu menu) {  
  365.         // TODO Auto-generated method stub  
  366.         menu.add(111"更新");  
  367.         menu.add(122"退出");  
  368.         return true;  
  369.     }  
  370.       
  371.     @Override  
  372.     public boolean onOptionsItemSelected(MenuItem item) {  
  373.         switch(item.getItemId()) {  
  374.         case 1:  
  375.             UpdateManager updateManager = new UpdateManager(MainActivity.this);  
  376.             //检测更新  
  377.             updateManager.checkUpdate();  
  378.             break;  
  379.         case 2:  
  380.             finish();  
  381.             break;  
  382.         }  
  383.         return true;  
  384.     }  
  385.       
  386.     /** 
  387.      * 按键触发的事件 
  388.      */  
  389.     @Override  
  390.     public boolean onKeyDown(int keyCode, KeyEvent event) {  
  391.         if(keyCode == KeyEvent.KEYCODE_BACK  
  392.                 && event.getAction() == KeyEvent.ACTION_DOWN){  
  393.             if((System.currentTimeMillis() - exitTime > 2000)){  
  394.                 Toast.makeText(getApplicationContext(), R.string.backcancel  
  395.                         , Toast.LENGTH_LONG).show();  
  396.                 exitTime = System.currentTimeMillis();  
  397.             }  
  398.             else{  
  399.                 finish();  
  400.                 System.exit(0);  
  401.             }  
  402.             return true;  
  403.         }  
  404.         return super.onKeyDown(keyCode, event);  
  405.     }  
  406. }  
package com.xiaowu.news; 
 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.List; 
 
import org.json.JSONArray; 
import org.json.JSONObject; 
 
import android.app.Activity; 
import android.content.Intent; 
import android.graphics.Color; 
import android.graphics.drawable.ColorDrawable; 
import android.os.AsyncTask; 
import android.os.Bundle; 
import android.view.Gravity; 
import android.view.KeyEvent; 
import android.view.LayoutInflater; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.AdapterView; 
import android.widget.AdapterView.OnItemClickListener; 
import android.widget.Button; 
import android.widget.GridView; 
import android.widget.HorizontalScrollView; 
import android.widget.LinearLayout; 
import android.widget.LinearLayout.LayoutParams; 
import android.widget.ListView; 
import android.widget.ProgressBar; 
import android.widget.SimpleAdapter; 
import android.widget.TextView; 
import android.widget.Toast; 
 
import com.xiaowu.news.custom.ConstomSimpleAdapter; 
import com.xiaowu.news.model.Category; 
import com.xiaowu.news.service.SyncHttp; 
import com.xiaowu.news.update.UpdateManager; 
import com.xiaowu.news.util.DensityUtil; 
import com.xiaowu.news.util.StringUtil; 
 
/** 
 *  
 * @author wwj 
 *  
 */ 
public class MainActivity extends Activity { 
 
	private final int COLUMNWIDTH_PX = 56; 				// GridView每个单元格的宽度(像素) 
	private final int FLINGVELOCITY_PX = 800; 			// ViewFilper滑动的距离(像素) 
	private final int NEWSCOUNT = 5; 					// 显示新闻的条数 
	private final int SUCCESS = 0;						// 加载新闻成功 
	private final int NONEWS = 1;						// 没有新闻 
	private final int NOMORENEWS = 2;					// 没有更多新闻 
	private final int LOADERROR = 3;					// 加载失败 
 
	private long exitTime;								//按返回键退出的时间 
	private int mColumnWidth_dip;						 
	private int mFlingVelocity_dip; 
	private int mCid; 									// 新闻编号 
	private String mCategoryTitle;						// 新闻分类标题 
	private ListView mNewslist; 						// 新闻列表 
	private SimpleAdapter mNewslistAdapter; 			// 为新闻内容提供需要显示的列表 
	private ArrayList<HashMap<String, Object>> mNewsData; // 存储新闻信息的数据集合 
	private LayoutInflater mInflater; 					// 用来动态载入没有loadmore_layout界面 
	 
	private Button category_Button = null;				// 新闻分类标题栏的向右查看的按钮 
	 
	private HorizontalScrollView categoryScrollView = null;// 水平滚动图 
 
	private Button mTitleBarRefresh;					// 标题栏的刷新按钮 
	private ProgressBar mTitleBarProgress;				// 进度条 
	private Button mLoadmoreButton;						// 加载更多按钮 
 
	private LoadNewsAsyncTack mLoadNewsAsyncTack;		// 声明LoadNewsAsyncTack引用 
	 
 
	@Override 
	public void onCreate(Bundle savedInstanceState) { 
		super.onCreate(savedInstanceState); 
		setContentView(R.layout.news_home_layout); 
		 
		//通过id来获取按钮的引用 
		mTitleBarRefresh = (Button) findViewById(R.id.titlebar_refresh); 
		mTitleBarProgress = (ProgressBar) findViewById(R.id.titlebar_progress); 
		 
		mTitleBarRefresh.setOnClickListener(loadmoreListener); 
		// 将px转换为dip 
		mColumnWidth_dip = DensityUtil.px2dip(this, COLUMNWIDTH_PX); 
		mFlingVelocity_dip = DensityUtil.px2dip(this, FLINGVELOCITY_PX); 
		//初始化新闻分类的编号 
		mCid = 1; 
		mCategoryTitle = "焦点"; 
		mInflater = getLayoutInflater(); 
		//存储新闻信息的数据集合 
		mNewsData = new ArrayList<HashMap<String, Object>>(); 
		// 获取数组资源 
		String[] categoryArray = getResources().getStringArray( 
				R.array.categories); 
 
		// 定义一个List数组,用来存放HashMap对象 
		final List<HashMap<String, Category>> categories = new ArrayList<HashMap<String, Category>>(); 
		// 分割新闻字符串 
		for (int i = 0; i < categoryArray.length; i++) { 
			String temp[] = categoryArray[i].split("[|]"); 
			if (temp.length == 2) { 
				int cid = StringUtil.string2Int(temp[0]); 
				String title = temp[1]; 
				Category type = new Category(cid, title); 
				// 定义一个HashMap对象,用来存放键值对 
				HashMap<String, Category> hashMap = new HashMap<String, Category>(); 
				hashMap.put("category_title", type); 
				categories.add(hashMap); 
			} 
		} 
		ConstomSimpleAdapter categoryAdapter = new ConstomSimpleAdapter(this, 
				categories, R.layout.category_item_layout, 
				new String[] { "category_title" }, 
				new int[] { R.id.category_title }); 
		// 创建一个网格视图, 用于实现新闻标题的布局 
		GridView category = new GridView(this); 
		// 设置单元格的背景色为透明,这样选择分类时就不会显示黄色背景了 
		category.setSelector(new ColorDrawable(Color.TRANSPARENT)); 
		// 设置每一个新闻标题的宽度 
		category.setColumnWidth(mColumnWidth_dip); 
		// 设置网格视图的列数 
		category.setNumColumns(GridView.AUTO_FIT); 
		// 设置对齐方式 
		category.setGravity(Gravity.CENTER); 
		// 根据单元格的宽度和数目计算网格视图的宽度 
		int width = mColumnWidth_dip * categories.size(); 
		// 获取布局参数 
		LayoutParams params = new LayoutParams(width, LayoutParams.MATCH_PARENT); 
		// 设置参数 
		category.setLayoutParams(params); 
		// 设置Adapter 
		category.setAdapter(categoryAdapter); 
		// 通过ID获取LinearLayout布局对象 
		LinearLayout categoryLayout = (LinearLayout) findViewById(R.id.category_layout); 
		// 将网格视图组件添加到LinearLayout布局当中 
		categoryLayout.addView(category); 
 
		// 添加单元格点击事件 
		category.setOnItemClickListener(new OnItemClickListener() { 
			TextView categoryTitle; 
 
			@Override 
			public void onItemClick(AdapterView<?> parent, View view, 
					int position, long id) { 
				// TODO Auto-generated method stub 
				for (int i = 0; i < parent.getCount(); i++) { 
					categoryTitle = (TextView) parent.getChildAt(i); 
					categoryTitle.setTextColor(0XFFADB2AD); 
					categoryTitle.setBackgroundDrawable(null); 
 
				} 
				categoryTitle = (TextView) view; 
				categoryTitle.setTextColor(0xFFFFFFFF); 
				categoryTitle 
						.setBackgroundResource(R.drawable.image_categorybar_item_selected_background); 
				Toast.makeText(MainActivity.this, categoryTitle.getText(), 
						Toast.LENGTH_SHORT).show(); 
				//获取新闻分类编号 
				mCid = categories.get(position).get("category_title").getCid(); 
				mCategoryTitle = categories.get(position).get("category_title").getTitle(); 
				mLoadNewsAsyncTack = new LoadNewsAsyncTack(); 
				mLoadNewsAsyncTack.execute(0, true); 
			} 
 
		}); 
		 
		//第一次获取新闻列表 
		getSpecCatNews(mCid, mNewsData, 0, true); 
		// 箭头 
		categoryScrollView = (HorizontalScrollView) findViewById(R.id.categorybar_scrollView); 
		category_Button = (Button) findViewById(R.id.category_arrow_right); 
		category_Button.setOnClickListener(new OnClickListener() { 
 
			@Override 
			public void onClick(View v) { 
				// TODO Auto-generated method stub 
				categoryScrollView.fling(mFlingVelocity_dip); 
			} 
		}); 
 
		mNewslistAdapter = new SimpleAdapter(this, mNewsData, 
				R.layout.newslist_item_layout, new String[] { 
						"newslist_item_title", "newslist_item_digest", 
						"newslist_item_source", "newslist_item_ptime" }, 
				new int[] { R.id.newslist_item_title, 
						R.id.newslist_item_digest, R.id.newslist_item_source, 
						R.id.newslist_item_ptime }); 
		mNewslist = (ListView) findViewById(R.id.news_list); 
		 
		View footerView = mInflater.inflate(R.layout.loadmore_layout, null); 
		//在LiseView下面添加“加载更多” 
		mNewslist.addFooterView(footerView); 
		//显示列表 
		mNewslist.setAdapter(mNewslistAdapter); 
		 
		mNewslist.setOnItemClickListener(new OnItemClickListener() { 
 
			@Override 
			public void onItemClick(AdapterView<?> parent, View view, 
					int position, long id) { 
				// TODO Auto-generated method stub 
				Intent intent = new Intent(MainActivity.this, 
						NewsDetailActivity.class); 
				intent.putExtra("categoryTitle", mCategoryTitle); 
				intent.putExtra("newsData", mNewsData); 
				intent.putExtra("position", position); 
				startActivity(intent); 
			} 
 
		}); 
 
		mLoadmoreButton = (Button) findViewById(R.id.loadmore_btn); 
		mLoadmoreButton.setOnClickListener(loadmoreListener); 
		 
	} 
 
	/** 
	 * 获取指定类型的新闻列表 
	 *  
	 * @param cid 
	 * @return 
	 */ 
	private int getSpecCatNews(int cid, List<HashMap<String, Object>> newsList, 
			int startnid, boolean firstTime) { 
 
		// 如果是第一次加载的话 
		if (firstTime) { 
			newsList.clear(); 
		} 
		//本机:http://10.0.2.2:8080/web/getSpecifyCategoryNews 
		//wifi局域网:192.168.220.1 
		String url = "http://10.0.2.2:8080/web/getSpecifyCategoryNews"; 
		String params = "startnid=" + startnid + "&count=" + NEWSCOUNT 
				+ "&cid=" + cid; 
		SyncHttp syncHttp = new SyncHttp(); 
 
		try { 
			// 通过Http协议发送Get请求,返回字符串 
			String retStr = syncHttp.httpGet(url, params); 
			JSONObject jsonObject = new JSONObject(retStr); 
			int retCode = jsonObject.getInt("ret"); 
			if (retCode == 0) { 
				JSONObject dataObj = jsonObject.getJSONObject("data"); 
				// 获取返回数目 
				int totalNum = dataObj.getInt("totalnum"); 
				if (totalNum > 0) { 
					// 获取返回新闻集合 
					JSONArray newslistArray = dataObj.getJSONArray("newslist"); 
					// 将用JSON格式解析的数据添加到数据集合当中 
					for (int i = 0; i < newslistArray.length(); i++) { 
						JSONObject newsObject = (JSONObject) newslistArray 
								.opt(i); 
						HashMap<String, Object> hashMap = new HashMap<String, Object>(); 
						hashMap.put("nid", newsObject.getInt("nid")); 
						hashMap.put("newslist_item_title", 
								newsObject.getString("title")); 
						hashMap.put("newslist_item_digest", 
								newsObject.getString("digest")); 
						hashMap.put("newslist_item_source", 
								newsObject.getString("source")); 
						hashMap.put("newslist_item_ptime", 
								newsObject.getString("ptime")); 
						hashMap.put("newslist_item_comments", 
								newsObject.getInt("commentcount")); 
						newsList.add(hashMap); 
					} 
					return SUCCESS; 
				} else { 
					//第一次加载新闻列表 
					if (firstTime) { 
						return NONEWS;			//没有新闻 
					} else { 
						return NOMORENEWS;		//没有更多新闻 
					} 
				} 
			} else { 
				return LOADERROR;			//加载新闻失败 
			} 
		} catch (Exception e) { 
			// TODO Auto-generated catch block 
			e.printStackTrace(); 
			return LOADERROR;			//加载新闻失败 
		} 
	} 
 
	/** 
	 * 为“加载更多”按钮定义匿名内部类 
	 */ 
	private OnClickListener loadmoreListener = new OnClickListener() { 
 
		@Override 
		public void onClick(View v) { 
			mLoadNewsAsyncTack = new LoadNewsAsyncTack(); 
			switch (v.getId()) { 
			//点击加载更多 
			case R.id.loadmore_btn: 
				mLoadNewsAsyncTack.execute(mNewsData.size(), false);	//不是第一次加载新闻里列表 
				break; 
			//点击刷新按钮 
			case R.id.titlebar_refresh: 
				mLoadNewsAsyncTack.execute(0, true); 
				break; 
			} 
		} 
	}; 
 
	/** 
	 * 异步更新UI 
	 * @author wwj 
	 * 
	 */ 
	private class LoadNewsAsyncTack extends AsyncTask<Object, Integer, Integer> { 
 
		//准备运行 
		@Override 
		protected void onPreExecute() { 
			mTitleBarRefresh.setVisibility(View.GONE); 
			mTitleBarProgress.setVisibility(View.VISIBLE); 
			mLoadmoreButton.setText(R.string.loadmore_text); 
		} 
		//在后台运行 
		@Override 
		protected Integer doInBackground(Object... params) { 
			return getSpecCatNews(mCid, mNewsData, (Integer) params[0], 
					(Boolean) params[1]); 
		} 
		//完成后台任务 
		@Override 
		protected void onPostExecute(Integer result) { 
			switch (result) { 
			//该栏目没有新闻 
			case NONEWS: 
				Toast.makeText(MainActivity.this, R.string.nonews, Toast.LENGTH_SHORT) 
						.show(); 
				break; 
			//该栏目没有更多新闻 
			case NOMORENEWS: 
				Toast.makeText(MainActivity.this, R.string.nomorenews, 
						Toast.LENGTH_SHORT).show(); 
				break; 
			//加载失败 
			case LOADERROR: 
				Toast.makeText(MainActivity.this, R.string.loadnewserror, Toast.LENGTH_SHORT) 
						.show(); 
				break; 
			} 
			mTitleBarRefresh.setVisibility(View.VISIBLE);			//刷新按钮设置为可见 
			mTitleBarProgress.setVisibility(View.GONE);				//进度条设置为不可见 
			mLoadmoreButton.setText(R.string.loadmore_btn);			//按钮信息替换为“加载更多” 
			mNewslistAdapter.notifyDataSetChanged();				//通知ListView更新数据 
		} 
	} 
	 
	/** 
	 * 添加菜单 
	 */ 
	@Override 
	public boolean onCreateOptionsMenu(Menu menu) { 
		// TODO Auto-generated method stub 
		menu.add(1, 1, 1, "更新"); 
		menu.add(1, 2, 2, "退出"); 
		return true; 
	} 
	 
	@Override 
	public boolean onOptionsItemSelected(MenuItem item) { 
		switch(item.getItemId()) { 
		case 1: 
			UpdateManager updateManager = new UpdateManager(MainActivity.this); 
			//检测更新 
			updateManager.checkUpdate(); 
			break; 
		case 2: 
			finish(); 
			break; 
		} 
		return true; 
	} 
	 
	/** 
	 * 按键触发的事件 
	 */ 
	@Override 
	public boolean onKeyDown(int keyCode, KeyEvent event) { 
		if(keyCode == KeyEvent.KEYCODE_BACK 
    			&& event.getAction() == KeyEvent.ACTION_DOWN){ 
    		if((System.currentTimeMillis() - exitTime > 2000)){ 
    			Toast.makeText(getApplicationContext(), R.string.backcancel 
    					, Toast.LENGTH_LONG).show(); 
    			exitTime = System.currentTimeMillis(); 
    		} 
    		else{ 
    			finish(); 
    			System.exit(0); 
    		} 
    		return true; 
    	} 
		return super.onKeyDown(keyCode, event); 
	} 
} 


 

主界面的业务逻辑实现,要一步就实现是非常困难的,因为项目总是从简单到复杂,所以小巫只把关键点说一下就行了:

这里主要有三个关键点:

1.分类栏的实现?

首先创建一个GridView视图,通过GridView来填充数据,把每一类新闻分类显示到GridView视图中去,最后通过获取到界面布局中的LinearLayout对象,把GridView添加到LinearLayout布局当中去,最终实现效果。

2.获取新闻分类列表(对JSON格式数据的解析)?

JSON数据的解析并不算太难,主要把JSON数据的数据结构搞清楚,解析起来还是挺方便的。

进行解析虽然方便,但前提是要把数据得到,因为数据是要在服务器端得到,需要利用Android的Http通信来实现。

这里需要利用到httpGet还有httpPost方法,这个代码很需要贴一贴滴。自定义的SyncHttp类

  1. package com.xiaowu.news.service;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5.   
  6. import org.apache.http.HttpResponse;  
  7. import org.apache.http.HttpStatus;  
  8. import org.apache.http.client.HttpClient;  
  9. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  10. import org.apache.http.client.methods.HttpGet;  
  11. import org.apache.http.client.methods.HttpPost;  
  12. import org.apache.http.impl.client.DefaultHttpClient;  
  13. import org.apache.http.message.BasicNameValuePair;  
  14. import org.apache.http.params.BasicHttpParams;  
  15. import org.apache.http.params.HttpConnectionParams;  
  16. import org.apache.http.params.HttpParams;  
  17. import org.apache.http.protocol.HTTP;  
  18. import org.apache.http.util.EntityUtils;  
  19.   
  20. import com.xiaowu.news.model.Parameter;  
  21.   
  22. public class SyncHttp {  
  23.     /** 
  24.      * 通过Get方式发送请求 
  25.      * @param url 
  26.      * @param params 
  27.      * @return 
  28.      * @throws Exception 
  29.      */  
  30.     public String httpGet(String url, String params) throws Exception {  
  31.         String response = null//返回信息  
  32.         //拼接请求URl  
  33.         if(null != params && !params.equals("")) {  
  34.             url += "?" + params;  
  35.         }  
  36.           
  37.         int timeOutConnection = 3000;  
  38.         int timeOutSocket = 5000;   
  39.         HttpParams httpParams = new BasicHttpParams();  
  40.         HttpConnectionParams.setConnectionTimeout(httpParams, timeOutConnection);  
  41.         HttpConnectionParams.setSoTimeout(httpParams, timeOutSocket);  
  42.           
  43.         //构造HttpClient实例  
  44.         HttpClient httpClient = new DefaultHttpClient();  
  45.         //创建GET方法实例  
  46.         HttpGet httpGet = new HttpGet(url);  
  47.         try {  
  48.             HttpResponse httpResponse = httpClient.execute(httpGet);  
  49.             int statusCode = httpResponse.getStatusLine().getStatusCode();  
  50.             if(statusCode == HttpStatus.SC_OK) {  
  51.                 //获得返回结果  
  52.                 response = EntityUtils.toString(httpResponse.getEntity());  
  53.             }  
  54.             else{  
  55.                 response = "返回码:" + statusCode;  
  56.             }  
  57.         } catch (Exception e) {  
  58.             // TODO: handle exception  
  59.             throw new Exception(e);  
  60.         }  
  61.         return response;  
  62.     }  
  63.       
  64.     /** 
  65.      * 通过post方式发送请求 
  66.      * @param url 
  67.      * @param params 
  68.      * @return 
  69.      * @throws Exception 
  70.      */  
  71.     public String httpPost(String url, List<Parameter> params) throws Exception {  
  72.         String response  = null;  
  73.         int timeOutConnection = 3000;  
  74.         int timeOutSocket = 5000;   
  75.         HttpParams httpParams = new BasicHttpParams();  
  76.         HttpConnectionParams.setConnectionTimeout(httpParams, timeOutConnection);  
  77.         HttpConnectionParams.setSoTimeout(httpParams, timeOutSocket);  
  78.           
  79.           
  80.         //构造HttpClient实例  
  81.         HttpClient httpClient = new DefaultHttpClient();  
  82.         HttpPost httpPost = new HttpPost(url);  
  83.         if(params.size() > 0) {  
  84.             //设置post请求参数  
  85.             httpPost.setEntity(new UrlEncodedFormEntity(buildNameValuePair(params), HTTP.UTF_8));  
  86.         }  
  87.           
  88.         //使用execute方法发送Http Post 请求,并返回HttpResponse对象  
  89.         HttpResponse httpResponse = httpClient.execute(httpPost);  
  90.           
  91.         int statusCode = httpResponse.getStatusLine().getStatusCode();  
  92.         if(statusCode == HttpStatus.SC_OK) {  
  93.             //获得返回结果  
  94.             response = EntityUtils.toString(httpResponse.getEntity());  
  95.         }  
  96.         else {  
  97.             response = "返回码:" + statusCode;  
  98.         }  
  99.         return response;  
  100.     }  
  101.           
  102.     /** 
  103.      * 把Paramster类型集合转换为NameValuePair类型集合 
  104.      * @param params 
  105.      * @return 
  106.      */  
  107.     private List<BasicNameValuePair> buildNameValuePair (List<Parameter> params) {  
  108.         List<BasicNameValuePair> result = new ArrayList<BasicNameValuePair>();  
  109.         for(Parameter param : params) {  
  110.             BasicNameValuePair pair = new BasicNameValuePair(param.getName(), param.getValue());  
  111.             result.add(pair);  
  112.         }  
  113.         return result;  
  114.     }  
  115. }  
package com.xiaowu.news.service; 
 
import java.util.ArrayList; 
import java.util.List; 
 
import org.apache.http.HttpResponse; 
import org.apache.http.HttpStatus; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.entity.UrlEncodedFormEntity; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.message.BasicNameValuePair; 
import org.apache.http.params.BasicHttpParams; 
import org.apache.http.params.HttpConnectionParams; 
import org.apache.http.params.HttpParams; 
import org.apache.http.protocol.HTTP; 
import org.apache.http.util.EntityUtils; 
 
import com.xiaowu.news.model.Parameter; 
 
public class SyncHttp { 
	/** 
	 * 通过Get方式发送请求 
	 * @param url 
	 * @param params 
	 * @return 
	 * @throws Exception 
	 */ 
	public String httpGet(String url, String params) throws Exception { 
		String response = null;	//返回信息 
		//拼接请求URl 
		if(null != params && !params.equals("")) { 
			url += "?" + params; 
		} 
		 
		int timeOutConnection = 3000; 
		int timeOutSocket = 5000;  
		HttpParams httpParams = new BasicHttpParams(); 
		HttpConnectionParams.setConnectionTimeout(httpParams, timeOutConnection); 
		HttpConnectionParams.setSoTimeout(httpParams, timeOutSocket); 
		 
		//构造HttpClient实例 
		HttpClient httpClient = new DefaultHttpClient(); 
		//创建GET方法实例 
		HttpGet httpGet = new HttpGet(url); 
		try { 
			HttpResponse httpResponse = httpClient.execute(httpGet); 
			int statusCode = httpResponse.getStatusLine().getStatusCode(); 
			if(statusCode == HttpStatus.SC_OK) { 
				//获得返回结果 
				response = EntityUtils.toString(httpResponse.getEntity()); 
			} 
			else{ 
				response = "返回码:" + statusCode; 
			} 
		} catch (Exception e) { 
			// TODO: handle exception 
			throw new Exception(e); 
		} 
		return response; 
	} 
	 
	/** 
	 * 通过post方式发送请求 
	 * @param url 
	 * @param params 
	 * @return 
	 * @throws Exception 
	 */ 
	public String httpPost(String url, List<Parameter> params) throws Exception { 
		String response  = null; 
		int timeOutConnection = 3000; 
		int timeOutSocket = 5000;  
		HttpParams httpParams = new BasicHttpParams(); 
		HttpConnectionParams.setConnectionTimeout(httpParams, timeOutConnection); 
		HttpConnectionParams.setSoTimeout(httpParams, timeOutSocket); 
		 
		 
		//构造HttpClient实例 
		HttpClient httpClient = new DefaultHttpClient(); 
		HttpPost httpPost = new HttpPost(url); 
		if(params.size() > 0) { 
			//设置post请求参数 
			httpPost.setEntity(new UrlEncodedFormEntity(buildNameValuePair(params), HTTP.UTF_8)); 
		} 
		 
		//使用execute方法发送Http Post 请求,并返回HttpResponse对象 
		HttpResponse httpResponse = httpClient.execute(httpPost); 
		 
		int statusCode = httpResponse.getStatusLine().getStatusCode(); 
		if(statusCode == HttpStatus.SC_OK) { 
			//获得返回结果 
			response = EntityUtils.toString(httpResponse.getEntity()); 
		} 
		else { 
			response = "返回码:" + statusCode; 
		} 
		return response; 
	} 
		 
	/** 
	 * 把Paramster类型集合转换为NameValuePair类型集合 
	 * @param params 
	 * @return 
	 */ 
	private List<BasicNameValuePair> buildNameValuePair (List<Parameter> params) { 
		List<BasicNameValuePair> result = new ArrayList<BasicNameValuePair>(); 
		for(Parameter param : params) { 
			BasicNameValuePair pair = new BasicNameValuePair(param.getName(), param.getValue()); 
			result.add(pair); 
		} 
		return result; 
	} 
} 

定义好了SyncHttp类之后,就可以通过调用httpGet方法来获取数据,在Activity的getSpecCatNews方法有详细实现,看一下就可以知道了。

3.异步更新UI的实现?

关于异步更新UI也算是一个比较难理解的东西,在Activity里定义了一个继承AsyncTask类的内部类,并实现三个方法,比较灵活。具体实现看代码。

 

以上三点是小巫认为比较核心的地方,具体的需要动手之后才知道。

声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

发表评论
搜索
KIKK导航

KIKK导航

排行榜
关注我们

一个IT知识分享的公众号