您的位置:首页 > 移动开发 > Android开发

Android新闻客户端开发4--显示新闻详细内容业务逻辑实现

2013-11-01 17:06 951 查看

基于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;

/**
*@author coolszy
*@date Feb 19, 2012
*@blog 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。

 

 

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

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

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

原:http://blog.csdn.net/wwj_748/article/details/8619417

整个项目源码下载地址:http://download.csdn.net/detail/wwj_748/5052006
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐