android平台——移动SNS(三)

   最近做一个类似QQ空间的发布状态并且可以让用户进行评论和回复的一个玩意儿。

 

1,功能如下:

(1)登录用户发布状态

(2)可以查看自己发布过的所有状态;

(3)可以查看登录用户的好友动态,即所有好友的所有状态列表;

(4)可以查看每条状态(包括登录用户和好友的)下对应的评论和回复;

(5)状态列表的显示按时间顺序由新到旧显示,回复和评论按时间顺序由旧到新显示;

(6)评论和回复以树的形式用列表显示,相当于论坛树;

(7)点击每条评论或者回复,可以让用户选择对其进行回复或者进入发布者的主页

 

2,具体业务流程,可以看我前面写的一篇博客,android平台——移动SNS()

 

3,这里必须要提到的是一个界面的展示问题,通常我们用listview来显示列表,起初我是用activity继承ListActivity,但这样扩展性比较差,所以采用了如下方式,下面看看源代码。

 

msg_list.xml

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/default_bg"
    android:padding="5dip"
 >
 
 <TextView 
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="
      "
    android:textColor="#aa0000"
    android:id="@+id/who_state"
    />
 
  <LinearLayout
    
  android:layout_width="fill_parent"
     android:layout_height="wrap_content"
  android:orientation="horizontal">
  <EditText 
  android:id="@+id/msgContent"
  android:layout_weight="11"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  />
     <Button
     android:layout_weight="1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/msgSend_btn"
    android:text="
发表"
    />
    </LinearLayout>
   
    <ListView 
 
    android:id="@+id/listv" 
 
   android:layout_width="fill_parent" 
 
   android:layout_height="wrap_content" 
 
      />
  
</LinearLayout>

msglist_data.xml

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
 
   <LinearLayout
  android:layout_width="fill_parent"
     android:layout_height="wrap_content"
  android:orientation="horizontal">
    <ImageView
  android:id="@+id/msg_user_icon"
     android:layout_height="48dip"
     android:layout_width="48dip"
  android:layout_marginRight="5dip"/>
     
    <LinearLayout
  android:layout_width="fill_parent"
     android:layout_height="wrap_content"
  android:orientation="vertical">
   <LinearLayout
  android:layout_width="fill_parent"
     android:layout_height="wrap_content"
  android:orientation="horizontal">
   <TextView
    android:id="@+id/msg_username"
    android:textColor="#ffffd000"
    android:textStyle="bold"
    android:layout_weight="1.0"
    android:layout_width="wrap_content"
       android:layout_height="wrap_content"/>
  </LinearLayout>
     <TextView
   android:id="@+id/msg_update_body"
   android:textColor="@android:color/white"
   android:autoLink="all"
   android:layout_width="fill_parent"
      android:layout_height="wrap_content"/>
  
      <TextView
   android:id="@+id/msg_timestamp"
   android:layout_width="wrap_content"
      android:layout_height="wrap_content"/>
 
 </LinearLayout>
 
  </LinearLayout>
 
</LinearLayout>

 

public void onCreate(Bundle savedInstanceState) { 

    super.onCreate(savedInstanceState); 
    setContentView(R.layout.msg_list);
   
    //
初始化组件
    lv = (ListView)findViewById(R.id.listv);  
        
    
      
    //
首次请求服务器的url地址
    String path = HttpUtils.BASE_URL+"servlet/GetNewsServlet?uid="+uid+"&biz=getMsgs";
    loadView(path);  //
加载界面,将服务器获取数据填充
           
  }
 
// android delete avd -n tl3shi android create avd -n tl3shi -t 2  emulator -avd tl3shi

  public void loadView(String path){
   final String url = path;
   new Thread(new Runnable() {
   @Override
   public void run() {
    // TODO Auto-generated method stub
    //
异步方式获取服务器数据
     data = getData(url);
    
     //
开启UI线程,用于更新UI
     MsgListActivity.this.runOnUiThread(new Runnable()
     {
      
      @Override
      public void run()
      {
       // TODO Auto-generated method stub
       SimpleAdapter adapter = new SimpleAdapter(MsgListActivity.this,data,R.layout.msglist_data, 

                     new String[]{"title","info","time","img"}, 

                   new int[]{R.id.msg_username,R.id.msg_update_body,R.id.msg_timestamp,R.id.msg_user_icon}); 

          lv.setAdapter(adapter);
      }
     });
   }
   
   }).start();
   
    
  }

 

 

private List<Map<String, Object>> getData() { 

 

                    

               List<Map<String, Object>> list = new ArrayList<Map<String, Object>>() ;

                        String pathName = null;

                            try {

                                   pathName = HttpUtils.downloadFile("http://192.168.1.164:8082/xiaomii_android_server/photo.png");

                            } catch (Exception e1) {

                                   // TODO Auto-generated catch block

                                   e1.printStackTrace();

                            }

                                   BitmapFactory.Options options = new BitmapFactory.Options();

                       options.inSampleSize = 2;

 

                        Map<String, Object> map = new HashMap<String, Object>(); 

 

                       map.put("title", "G1"); 

 

                       map.put("info", "google 1"); 

                       map.put("time", "2011-2-22 11:11"); 

 

                       map.put("img", R.drawable.icon); 

 

                       list.add(map); 

 

                 

 

                       map = new HashMap<String, Object>(); 

 

                       map.put("title", "G2"); 

 

                        map.put("info", "google 2"); 

                        map.put("time", "2011-2-22 11:11"); 

 

//                      map.put("img", R.drawable.icon); 

                        map.put("img", pathName);

 

                       list.add(map); 

 

                  

 

                        map = new HashMap<String, Object>(); 

 

                       map.put("title", "G3"); 

 

                       map.put("info", "google 3"); 

                       map.put("time", "2011-2-22 11:11"); 

 

                       map.put("img", "/sdcard/xiaomii_android_client/notify/photo.png"); 

                      

//                                 try {

//                                        msg_user_icon.setImageBitmap(BitmapFactory.decodeFile(pathName));

//                                 } catch (Exception e) {

                                      // TODO Auto-generated catch block

//                                        e.printStackTrace();

//                                 }//, "/xiaomii_android_client/notify/");

 

                        list.add(map); 

 

                           

 

                        return list; 

 

                    } 

4,数据库(MySQL

CREATE TABLE msg (

   mid int(11) AUTO_INCREMENT NOT NULL ,

   uid int(11) NOT NULL ,

   name varchar(30) NOT NULL,

   facePic varchar(30) NOT NULL default '',

   motion varchar(30) NOT NULL default '',

   time datetime NOT NULL ,

   tomid int(11) NOT NULL ,

   touid int(11) NOT NULL ,

   toname varchar(20) default NULL,

   action varchar(30) default NULL,

   sub varchar(30) default NULL,

   par varchar(30) default NULL,

   vis varchar(30) default NULL,

   content Text default NULL,

   PRIMARY KEY  (mid)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

5,需要解决的相关问题,如果各位有好的解决办法,可以指点一二:

(1),将消息内容按照时间顺序显示,进一步,则初步显示指定条数,用户通过增加滚动事件或者按钮事件来读取更   多条数的  消息内容

按时间顺序显示好说,order by time即可,滚动事件则需要写数据的分页,而且还要考虑性能

 

(2),用户头像显示问题(获取到头像后如何处理,是否缓存到客户端,又如何进行图片缓存)

 

这里我用了一个文件下载类,根据数据库存的服务器头像路径,将头像下载到SD卡中,为了使得用户具有更好的用户体验,存在SD卡上的图片应将其后缀去掉,显示头像时也无需将后缀加上(android是在linux系统基础上的,不以后缀来识别文件名),只需写对SD卡上文件路径即可

文件下载类中,当SD卡上有同名文件存在时,则无需从服务器中下载,这样性能更好些。

 

(3),显示消息的回复条数问题

 

<1>看到网上如下内容,决定用SELECT   COUNT(*)

 

SELECT   COUNT(*)通常是对主键进行索引扫描,   SELECT   COUNT(COL)就不一定,   如果在COL上有索引,那么效率和COUNT(*)应该差不多,   如果没有那就比较讨厌,   要进行全表扫描,   效率肯定差.  

   

  SELECT   COUNT(*)SELECT   COUNT(COL)是不同的概念,   前者是统计表中的所有纪录总数,   而后者是计算表中COL<>NULL的纪录数.   所以得到的结果可能是不一样的.   具体用那个,还要看你的逻辑要求.

 

<2>从服务器请求状态列表时,则同时返回状态列表的每个状态的评论条数,可以将状态列表和评论条数都放在一个数据结构中,转成xml字符串,以逗号分割,返回到客户端,再将其取出,并解析xml.

 

(4),异步显示消息内容

 

new Thread(new Runnable() {
   @Override
   public void run() {
    // TODO Auto-generated method stub
    //
异步方式获取服务器数据
     data = getData(url);
    
     //
开启UI线程,用于更新UI
     MsgListActivity.this.runOnUiThread(new Runnable()
     {
      
      @Override
      public void run()
      {
       // TODO Auto-generated method stub
       SimpleAdapter adapter = new SimpleAdapter(MsgListActivity.this,data,R.layout.msglist_data, 

                     new String[]{"title","info","time","img"}, 

                   new int[]{R.id.msg_username,R.id.msg_update_body,R.id.msg_timestamp,R.id.msg_user_icon}); 

          lv.setAdapter(adapter);
      }
     });
   }
   
   }).start();

(5),只能评论无法回复的问题

Listview单击列表项弹出回复菜单即可,再次弹出一个编辑对话框,如下:

 

editmsg_dialog.xml

 

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="250px"

    android:layout_height="250px"

       >

   <EditText 

              android:id="@+id/msgedit_Content"

              android:layout_weight="2"

              android:layout_width="fill_parent"

              android:layout_height="fill_parent"

              />

     <Button

     android:layout_weight="1"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_gravity="right"

    android:id="@+id/msgeditBtn"

    android:text="回复"

    />

</LinearLayout>

 

 

final Dialog editdialog = new Dialog(MsgDetailActivity.this);

                     editdialog.setContentView(R.layout.editmsg_dialog);

                     Button msgeditBtn = (Button)editdialog.findViewById(R.id.msgeditBtn);

                     final EditText msgedit_Content = (EditText)editdialog.findViewById(R.id.msgedit_Content);

                     editdialog.setTitle("编辑回复内容");

                     editdialog.show();

 

(6),如何进一步减少与服务器端的交互次数,减少数据的读取时间,使得客户端性能达到最优化

(7)经常要实时更新数据

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值