当前位置: 代码迷 >> Android >> 基于Android的小巫快讯客户端开发-显示新闻详细内容业务逻辑实现
  详细解决方案

基于Android的小巫快讯客户端开发-显示新闻详细内容业务逻辑实现

热度:39   发布时间:2016-05-01 11:31:19.0
基于Android的小巫新闻客户端开发---显示新闻详细内容业务逻辑实现

基于Android的小巫新闻客户端开发---显示新闻详细内容业务逻辑实现

 

 

2013年2月27日,继续小巫新闻客户端的开发。

上一篇忘记谈及一个比较重要的内容,有些网友留言给小巫问:Json数据的明细是怎样的?,在这里小巫先声明一点,小巫对Json数据的格式也是刚接触,这是稍微知道其的结构组成,关于是否尤其内容并不是很清楚。但小巫对与怎么进行JSON格式的解析已经比较清晰了。下面就接这篇博客来介绍一下,新闻详细内容的JSON数据是怎样的,通过浏览器得到的数据到底是怎样的。

 

如果得到小巫所共享的资源的话,服务端的项目是一个叫web的JavaEE项目,如果有看过里面的具体实现的话,读者可能就会明白,服务端是如何与数据库进行交互的了。那好,部署好项目到Tomcat中,在浏览器就可以得到相应的JSON数据源。

获取新闻详细内容的Servlet代码如下:注:(这是服务端的代码),关于解析JSON数据的解析,在介绍客户端业务逻辑实现的时候会说明。

package com.szy.web.servlet;import java.io.IOException;import java.io.PrintWriter;import java.util.ArrayList;import java.util.HashMap;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.json.JSONException;import org.json.JSONObject;import sun.reflect.generics.reflectiveObjects.NotImplementedException;import com.szy.web.dao.CommentDAO;import com.szy.web.dao.NewsDAO;import com.szy.web.model.News;import com.szy.web.util.TextUtility;/** [email protected] coolszy [email protected] Feb 19, 2012 [email protected] http://blog.92coding.com *http://localhost:8080/web/getNews?nid=1 */public class GetNewsServlet extends HttpServlet{	private static final long serialVersionUID = -7715894432269979527L;	public void doGet(HttpServletRequest request, HttpServletResponse response)			throws ServletException, IOException	{		response.setContentType("text/html;charset=UTF-8");		String nidStr= request.getParameter("nid");		int nid = 0;		nid = TextUtility.String2Int(nidStr);		JSONObject jObject = new JSONObject();		try		{			CommentDAO commentDAO = new CommentDAO();			long commentCount = commentDAO.getSpecifyNewsCommentsCount(nid);			NewsDAO newsDAO = new NewsDAO();			News news = newsDAO.getNews(nid);			JSONObject jObject2 = new JSONObject();			if (!TextUtility.isNull(news.getTitle()))			{				HashMap<String, Object> hashMap = new HashMap<String, Object>();												/***************后期增加代码,主要用于测试TextView显示图片功能********************/				String newsbody = news.getBody();				ArrayList<HashMap<String, Object>> list = new ArrayList<HashMap<String,Object>>();				HashMap<String, Object> hashMap1 = new HashMap<String, Object>();				hashMap1.put("index", 0);				hashMap1.put("type", "image");				hashMap1.put("value", "http://www.eportfolio.wtuc.edu.tw/blog/attach/35/16035/95/bf_22696_7751198_66497_4.jpg");								HashMap<String, Object> hashMap2 = new HashMap<String, Object>();				hashMap2.put("index", 1);				hashMap2.put("type", "text");				hashMap2.put("value", newsbody);								list.add(hashMap1);				list.add(hashMap2);			/********************************************************/								hashMap.put("nid", news.getNid());				hashMap.put("title", news.getTitle());				//hashMap.put("body", news.getBody());				hashMap.put("body", list);				hashMap.put("source", news.getSource());				hashMap.put("replycount", commentCount);				hashMap.put("ptime", news.getPtime());				hashMap.put("imgsrc", news.getImgSrc());				jObject2.put("news", hashMap);			}			jObject.put("ret", 0);			jObject.put("msg", "ok");			jObject.put("data", jObject2);		} catch (Exception e)		{			e.printStackTrace();			try			{				jObject.put("ret", 1);				jObject.put("msg", e.getMessage());				jObject.put("data", "");			} catch (JSONException ex)			{				ex.printStackTrace();			}		}		PrintWriter out = response.getWriter();		out.println(jObject);		out.flush();		out.close();	}	public void doPost(HttpServletRequest request, HttpServletResponse response)			throws ServletException, IOException	{		throw new NotImplementedException();	}}

 

 

这就是服务端从数据库获取新闻详细内容的Servlet,当然这只是Servlet的代码,查询数据库的代码需要到web项目查看。

在浏览器敲入如下URL:http://localhost:8080/web/getNews?nid=2

就会得到数据nid为2的新闻内容如下:

{"ret":0,"data":{"news":{"body":[{"index":0,"value":"http://www.eportfolio.wtuc.edu.tw/blog/attach/35/16035/95/bf_22696_7751198_66497_4.jpg","type":"image"},{"index":1,"value":"

新华网十八大快讯:党的十八届一中全会选举习近平、李克强、张德江、俞正声、刘云山、王岐山、张高丽为中央政治局常委。<\/p>","type":"text"}],"title":"党的十八届一中全会选举习近平、李克强、张德江、俞正声、刘云山、王岐山、张高丽为中央政治局常委 ","source":"来源: 新华网","nid":2,"replycount":1,"ptime":"2012年11月15日 11:45:36"}},"msg":"ok"}

 

这样看是比较乱的,需要将这些数据进行一下格式化,看起来比较舒服。

{  "ret": 0,   "data": {    "news": {      "body": [        {          "index": 0,           "value": "http://www.eportfolio.wtuc.edu.tw/blog/attach/35/16035/95/bf_22696_7751198_66497_4.jpg",           "type": "image"        },         {          "index": 1,           "value": " <p>新华网十八大快讯:党的十八届一中全会选举习近平、李克强、张德江、俞正声、刘云山、王岐山、张高丽为中央政治局常委。</p>",           "type": "text"        }      ],       "title": "党的十八届一中全会选举习近平、李克强、张德江、俞正声、刘云山、王岐山、张高丽为中央政治局常委 ",       "source": "来源: 新华网",       "nid": 2,       "replycount": 1,       "ptime": "2012年11月15日 11:45:36"    }  },   "msg": "ok"}


 

那好,关于JSON数据的明细,就说到这里。从格式化的JSON数据是可以很清楚得到新闻的组成结构的,接下来就是要在客户端解析这些数据,并把它们显示到手机界面上,这才是我们花那么大功夫去解析JSON数据的原因。

 

贴上代码之前,当然需要看一下最终需要实现的效果图:

    

 

关于这个界面我就不做过多的说明了,最重要的是具体实现。

package com.xiaowu.news;import java.io.Serializable;import java.util.ArrayList;import java.util.HashMap;import org.json.JSONArray;import org.json.JSONObject;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.LayoutInflater;import android.view.Menu;import android.view.MenuItem;import android.view.MotionEvent;import android.view.View;import android.view.View.OnClickListener;import android.view.View.OnTouchListener;import android.view.inputmethod.InputMethodManager;import android.widget.Button;import android.widget.EditText;import android.widget.ImageButton;import android.widget.LinearLayout;import android.widget.TextView;import android.widget.Toast;import android.widget.ViewFlipper;import com.xiaowu.news.service.SyncHttp;import com.xiaowu.news.thread.PostCommentsThread;public class NewsDetailActivity extends Activity {	private final int FINISH = 0;				//代表线程的状态的结束	private LayoutInflater mNewsbodyLayoutInflater;	private ViewFlipper mNewsBodyFlipper;		//屏幕切换控件	private ArrayList<HashMap<String, Object>> mNewsData;	private float mStartX;						//手指按下的开始位置	private int mPosition = 0;					//点击新闻位置			private int mCursor = 0;					//用来标记新闻点击的位置	private int mNid;							//新闻编号	private Button mNewsDetailTitleBarComm;		//显示评论条数的按钮	private ConstomTextView mNewsBodyDetail;	//新闻详细内容	private LinearLayout mNewsReplyEditLayout;	//新闻回复的布局	private LinearLayout mNewsReplyImgLayout;	//新闻图片回复的布局	private EditText mNewsReplyEditText;		//新闻回复的文本框	private ImageButton mShareNewsButton;		//分享新闻的按钮	private ImageButton mFavoritesButton;		//收藏新闻的按钮	private boolean keyboardShow;				//键盘是否显示	private Handler mHandler = new Handler() {		@SuppressWarnings("unchecked")		@Override		public void handleMessage(Message msg) {			// TODO Auto-generated method stub			switch (msg.arg1) {			case FINISH:				//把获取到的新闻显示到界面上				ArrayList<HashMap<String, Object>> bodyList = (ArrayList<HashMap<String, Object>>) msg.obj;				mNewsBodyDetail.setText(bodyList);				break;			}		}	};	@SuppressWarnings("unchecked")	@Override	protected void onCreate(Bundle savedInstanceState) {		// TODO Auto-generated method stub		super.onCreate(savedInstanceState);		setContentView(R.layout.newsdetails_layout);		mNewsReplyEditLayout = (LinearLayout) findViewById(R.id.news_reply_edit_layout);		mNewsReplyImgLayout = (LinearLayout) findViewById(R.id.news_reply_img_layout);				Button newsDetailPrev = (Button) findViewById(R.id.newsdetail_titlebar_previous);		Button newsDetailNext = (Button) findViewById(R.id.newsdetail_titlebar_next);		mNewsDetailTitleBarComm = (Button) findViewById(R.id.newsdetail_titlebar_comments);		mNewsReplyEditText = (EditText) findViewById(R.id.news_reply_edittext);		mShareNewsButton = (ImageButton) findViewById(R.id.news_share_btn);		mFavoritesButton = (ImageButton) findViewById(R.id.news_favorites_btn);						NewsDetailOnClickListener newsDetailOnClickListener = new NewsDetailOnClickListener();				newsDetailPrev.setOnClickListener(newsDetailOnClickListener);		newsDetailNext.setOnClickListener(newsDetailOnClickListener);		mNewsDetailTitleBarComm.setOnClickListener(newsDetailOnClickListener);		mShareNewsButton.setOnClickListener(newsDetailOnClickListener);		mFavoritesButton.setOnClickListener(newsDetailOnClickListener);				Button newsReplyPost = (Button) findViewById(R.id.news_reply_post);		newsReplyPost.setOnClickListener(newsDetailOnClickListener);		ImageButton newsReplyImgBtn = (ImageButton) findViewById(R.id.news_reply_img_btn);		newsReplyImgBtn.setOnClickListener(newsDetailOnClickListener);						//获取传送的数据		Intent intent = getIntent();		Bundle bundle = intent.getExtras();		String categoryName = bundle.getString("categoryTitle");		TextView titleBarTitle = (TextView) findViewById(R.id.newsdetail_titlebar_title);		//设置标题栏的标题		titleBarTitle.setText(categoryName);		//获取新闻集合		Serializable serializable = bundle.getSerializable("newsData");		mNewsData = (ArrayList<HashMap<String, Object>>) serializable;		//获取点击位置		mCursor = mPosition = bundle.getInt("position");				mNewsBodyFlipper = (ViewFlipper) findViewById(R.id.news_body_flipper);		// 获取LayoutInflater对象		mNewsbodyLayoutInflater = getLayoutInflater();				inflateView(0);		//启动线程		new UpdateNewsThread().start();	}	/**	 * 显示上一条新闻	 */	private void showPrevious() {		if(mPosition > 0) {			mPosition--;			//记录当前新闻编号			HashMap<String, Object> hashMap = mNewsData.get(mPosition);			mNid = (Integer) hashMap.get("nid");			if(mCursor > mPosition){				mCursor = mPosition;				inflateView(0);				mNewsBodyFlipper.showNext();			}			mNewsBodyFlipper.setInAnimation(this, R.anim.push_right_in);	//设置下一页进来时的动画			mNewsBodyFlipper.setOutAnimation(this, R.anim.push_right_out);	//设置当前页出去的动画			mNewsBodyFlipper.showPrevious();		}		else {			Toast.makeText(NewsDetailActivity.this, "没有上一篇新闻", Toast.LENGTH_SHORT).show();		}	}	/**	 * 显示下一条新闻	 */	private void showNext() {		if(mPosition < mNewsData.size() - 1){			// 设置下一屏动画			mNewsBodyFlipper.setInAnimation(this, R.anim.push_left_in);			mNewsBodyFlipper.setOutAnimation(this, R.anim.push_left_out);			mPosition++;			//记录当前新闻编号			HashMap<String, Object> hashMap = mNewsData.get(mPosition);			mNid = (Integer) hashMap.get("nid");			if(mPosition >= mNewsBodyFlipper.getChildCount()){				inflateView(mNewsBodyFlipper.getChildCount());			}			mNewsBodyFlipper.showNext();		} else {			Toast.makeText(NewsDetailActivity.this, "没有下篇新闻", Toast.LENGTH_SHORT).show();		}	}	private void inflateView(int index) {		//获取点击新闻信息		HashMap<String, Object> hashMap = mNewsData.get(mPosition);		mNid = (Integer) hashMap.get("nid");		View mNewsBodyView = mNewsbodyLayoutInflater.inflate(				R.layout.newsbody_layout, null);		mNewsDetailTitleBarComm.setText(hashMap.get("newslist_item_comments").toString() + "跟帖");		//新闻标题		TextView newsTitle = (TextView) mNewsBodyView				.findViewById(R.id.news_body_title);		newsTitle.setText(hashMap.get("newslist_item_title").toString());		//新闻的出处和发布时间		TextView newsPtimeAndSource = (TextView) mNewsBodyView				.findViewById(R.id.news_body_ptime_source);		newsPtimeAndSource.setText(hashMap.get("newslist_item_source").toString() 				+ "		" + hashMap.get("newslist_item_ptime").toString());		mNewsBodyDetail = (ConstomTextView) mNewsBodyView				.findViewById(R.id.news_body_details);		mNewsBodyDetail.setText(getNewsBody());		mNewsBodyFlipper.addView(mNewsBodyView, index);		mNewsBodyDetail.setOnTouchListener(new NewsBodyOntouchListener());	}	// 定义内部类--用于处理标题栏的按钮的触发事件	private class NewsDetailOnClickListener implements OnClickListener {		@Override		public void onClick(View v) {			InputMethodManager m = (InputMethodManager) mNewsReplyEditText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);			// TODO Auto-generated method stub			switch (v.getId()) {			//上一篇			case R.id.newsdetail_titlebar_previous:				showPrevious();				break;			//下一篇			case R.id.newsdetail_titlebar_next:				showNext();				break;			//跟帖			case R.id.newsdetail_titlebar_comments:				Intent intent = new Intent(NewsDetailActivity.this,						CommentsActivity.class);				intent.putExtra("nid", mNid);				startActivity(intent);				break;			//“写跟帖”图片			case R.id.news_reply_img_btn:				mNewsReplyEditLayout.setVisibility(View.VISIBLE);				mNewsReplyImgLayout.setVisibility(View.GONE);				mNewsReplyEditText.requestFocus();				//显示输入法				m.toggleSoftInput(0, InputMethodManager.SHOW_IMPLICIT);				keyboardShow = true;				break;			//分享按钮			case R.id.news_share_btn:				Intent shareIntent = new Intent(Intent.ACTION_SEND);				//纯文本				shareIntent.setType("text/plain");				shareIntent.putExtra(Intent.EXTRA_SUBJECT, "分享");				shareIntent.putExtra(Intent.EXTRA_TEXT, "我想将这个分享给你...."+ getTitle());				startActivity(Intent.createChooser(shareIntent, getTitle()));				break;			//收藏按钮			case R.id.news_favorites_btn:				Toast.makeText(NewsDetailActivity.this, "收藏成功", Toast.LENGTH_SHORT).show();				break;			//发表按钮			case R.id.news_reply_post:				//隐藏输入法				m.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);				String str = mNewsReplyEditText.getText().toString();				if(str.equals("")){					Toast.makeText(NewsDetailActivity.this, "不能为空",							Toast.LENGTH_SHORT).show();				}				else {					mNewsReplyEditLayout.post(new PostCommentsThread(mNid, "广州市",							str + "",							new NewsDetailActivity()));					mNewsReplyEditLayout.setVisibility(View.GONE);					mNewsReplyImgLayout.setVisibility(View.VISIBLE);				}				break;			}		}	}	private class NewsBodyOntouchListener implements OnTouchListener {		@Override		public boolean onTouch(View v, MotionEvent event) {			// TODO Auto-generated method stub			switch (event.getAction()) {				//手指按下			case MotionEvent.ACTION_DOWN:				if(keyboardShow){					mNewsReplyEditLayout.setVisibility(View.GONE);					mNewsReplyImgLayout.setVisibility(View.VISIBLE);					//隐藏输入法					InputMethodManager m = (InputMethodManager) mNewsReplyEditText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);					m.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);					keyboardShow = false;				}				//得到按下的横坐标的位置				mStartX = event.getX();				break;			case MotionEvent.ACTION_UP:				// 往左滑动				if (event.getX() < mStartX) {					showNext();				}				// 往右滑动				else if (event.getX() > mStartX) {					showPrevious();				}				break;			}			return true;		}	}		/**	 * 定义一个线程类,用来更新获取到新闻的信息	 * @author Administrator	 *	 */	private class UpdateNewsThread extends Thread {		@Override		public void run() {			// TODO Auto-generated method stub			ArrayList<HashMap<String, Object>> newsStr = getNewsBody();			Message msg = mHandler.obtainMessage();	//获取msg			msg.arg1 = FINISH;						msg.obj = newsStr;			mHandler.sendMessage(msg);	//给Handler发送信息		}	}			/**	 * 获取新闻详细信息	 * @return	 */	private ArrayList<HashMap<String, Object>> getNewsBody(){		//String retStr = "网络连接失败,请稍后再试";		ArrayList<HashMap<String, Object>> bodylist = new ArrayList<HashMap<String,Object>>();				SyncHttp syncHttp = new SyncHttp();		//模拟器:url = "http://10.0.2.2:8080/web/getNews";		//本机:http://127.0.0.1:8080		//wifi局域网:http://192.168.220.1:8080		String url = "http://10.0.2.2:8080/web/getNews";		String params = "nid=" + mNid;		try {			String retString = syncHttp.httpGet(url, params);			JSONObject  jsonObject = new JSONObject(retString);			//获取返回码,0表示成功			int retCode = jsonObject.getInt("ret");			if(retCode == 0) {				JSONObject dataObject = jsonObject.getJSONObject("data");				JSONObject newsObject = dataObject.getJSONObject("news");				//retStr = newsObject.getString("body");				JSONArray bodyArray = newsObject.getJSONArray("body");				for(int i = 0; i < bodyArray.length(); i++) {					JSONObject object = (JSONObject) bodyArray.opt(i);					HashMap<String, Object> hashMap = new HashMap<String, Object>();					hashMap.put("index", object.get("index"));					hashMap.put("type", object.get("type"));					hashMap.put("value", object.get("value"));					bodylist.add(hashMap);				}			}		} catch (Exception e) {			// TODO: handle exception			e.printStackTrace();		}		return bodylist;	}			@Override	public boolean onCreatePanelMenu(int featureId, Menu menu) {		// TODO Auto-generated method stub		menu.add(0, 0, 0, "分享");		return true;	}		@Override	public boolean onOptionsItemSelected(MenuItem item) {		// TODO Auto-generated method stub		switch(item.getItemId()) {		case 0:			Intent shareIntent = new Intent(Intent.ACTION_SEND);			//纯文本			shareIntent.setType("text/plain");			shareIntent.putExtra(Intent.EXTRA_SUBJECT, "分享");			shareIntent.putExtra(Intent.EXTRA_TEXT, "我想把这个分享给你:" + getTitle());			shareIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);			startActivity(Intent.createChooser(shareIntent, getTitle()));			System.out.println(getTitle());			break;					}		return super.onOptionsItemSelected(item);	}}


 

 

这段代码设计到以下几个关键点:

1.异步更新新闻详细内容。 这里是用Handler来实现线程异步。

2.实现上下篇新闻切换的功能。

3.自定义TextView的实现类ConstomTextView。

 

 

关于上面的代码已经实现得比较完善了,不知道是否还可以进行优化。

那么关于新闻详细内容显示的业务逻辑实现就写到这里,然后关于小巫新闻客户端开发的系列博客就暂时记录到这里,感谢网友们的支持。因为新闻回复的内容具体实现没什么可说的,只要把前面的业务逻辑实现弄懂了,新闻回复的业务逻辑也就没什么难的。

  如果网友们对小巫新闻客户端那部分有疑问,可以给我留言,小巫会把自己知道的东西都写出来。

 

 

 

 

  相关解决方案