Android实战——之反序列化实例

首先介绍下反序列化的概念和使用场景:

一、为什么要进行序列化
再介绍之前,我们有必要先了解下对象的生命周期,我们知道Java中的对象都是存在于堆内存中的,而堆内存是可以被垃圾回收器不定期回收的。从对象被创建到被回收这一段时间就是Java对象的生命周期,也即Java对象只存活于这个时间段内。对象被垃圾回收器回收意味着对象和对象中的成员变量所占的内存也就被回收,这意味着我们就再也得不到该对象的任何内容了,因为已经被销毁了嘛,当然我们可以再重新创建,但这时的对象的各种属性都又被重新初始化了。所以如果我们需要保存某对象的状态,然后再在未来的某段时间将该对象再恢复出来的话,则必须要在对象被销毁即被垃圾回收器回收之前保存对象的状态。要保存对象状态的话,我们可以使用文件、数据库,也可以使用序列化,这里我们主要介绍对象序列化。我们很有必要了解这方面的内容,因为对象序列化不仅在保存对象状态时可以被用到(对象持久化),在Java中的远程方法调用RMI也会被用到,在网络中要传输对象的话,则必须要对对象进行序列化,关于RMI有机会我会再专门开贴介绍。

简单总结起来,进行对象序列化的话的主要原因就是实现对象持久化和进行网络传输,这里先只介绍怎样通过对象序列化保存对象的状态。

二、什么情况下需要序列化   
    a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
    b)当你想用套接字在网络上传送对象的时候;
    c)当你想通过RMI传输对象的时候;

二:实际场景:在项目中遇到主页显示的listview中的item,点击跳转到详情页,把数据带过去并显示,就像新浪微博的效果:点击某个微博,跳转到微博的详情页。那么如何实现呢?下面我们通过一个简单的例子来介绍下如何进行对象序列化。

三.  示例

   在实体类HotTopicBean(热门话题)中一共有如下对象

    public String per_name;
    public String userimgUrl;   //用户头像地址
    public String hot_content;
    public String hot_title;
    public String update_time;  // 发表时间
    public int fabulousnum;     //点赞数目
    public String commentstr;   //点赞内容
    public int commentnum;      //评论数目
    public long postId;         //帖子ID
    public long userID;         //用户ID
     首先是从服务器拉取数据,json格式的,然后解析把 HotTopicBean创建的对象实例化,这里不介绍了,着重介绍如何序列化和反序列化。

    实现方法:在Intent中我们使用putExtras方法携带数据,将数据存放到Bundle中,然后putExtras带上Bundle参数,代码如下:

   adapter文件:

package yx.communitysocket.com.socket.adapter;

/**
 * Created by deng.jun on 2016/10/8.
 */

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import yx.communitysocket.com.socket.bean.HotTopicBean;
import yx.communitysocket.com.socket.utils.ImageLoader;
import yx.communitysocket.com.socket.view.HotCommentsDetailPage;
import yx.communitysocket.com.socket.view.MainActivity;
import yx.communitysocket.R;       
import yx.communitysocket.com.socket.view.MyListView;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.text.Layout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;


public class HotGameAdapter extends BaseAdapter {
    private List hotTopicItemList;
    LayoutInflater inflater; // 实例化每个item新闻
    int m_layoutID;
    Context mContext;
    public  final static String SER_KEY = "com.socket.adapter.HotGameAdapter.Serializeable";
    private int mStart, mEnd;
    public static String[] URLS;
    private ImageLoader mImageLoader;

    public HotGameAdapter(Context context, List hotTopicItemList, int layoutID) {
        this.hotTopicItemList = hotTopicItemList;
        this.inflater = LayoutInflater.from(context);
        this.m_layoutID = layoutID;
        mContext = context;
        mImageLoader = new ImageLoader();
    }

    @Override
    public int getCount() {
        return hotTopicItemList.size();
    }

    @Override
    public Object getItem(int position) {
        return hotTopicItemList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }


    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder = null;
        if (convertView == null) {
            viewHolder = new ViewHolder();
            convertView = inflater.inflate(R.layout.hottopicdj_layout, null);

            // item点击事件
            convertView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.i("click---------------->", "哈哈点击了");
//					Intent intent=new Intent(mContext, HotDetailsPage.class);
//					intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) ;
//					mContext.startActivity(intent);
                    SerializeMethod(position);
                }
            });

            viewHolder.ivIcon = (ImageView) convertView
                    .findViewById(R.id.iv_icon);
            viewHolder.hot_title = (TextView) convertView
                    .findViewById(R.id.tv_title);
            viewHolder.hot_content = (TextView) convertView
                    .findViewById(R.id.tv_comment);
            viewHolder.per_name = (TextView) convertView
                    .findViewById(R.id.tv_name);
            viewHolder.update_time = (TextView) convertView
                    .findViewById(R.id.tv_time);
            viewHolder.hot_zan_btn = (Button) convertView
                    .findViewById(R.id.hot_zan_btn);
            viewHolder.hot_pinlun_btn = (Button) convertView
                    .findViewById(R.id.hot_pinlun_btn);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        String imgUrl=hotTopicItemList.get(position).userimgUrl;
//		viewHolder.ivIcon.setImageBitmap(getBitmap(imgUrl));  不能直接在主线程更新图片! 使用异步或者多线程的方式!
        viewHolder.ivIcon.setTag(imgUrl);  //用图片地址为图片做标记

        mImageLoader.showImageByAsyncTask(viewHolder.ivIcon, imgUrl);

    //    mImageLoader.showImageByThread(viewHolder.ivIcon, imgUrl);


        viewHolder.per_name.setText(hotTopicItemList.get(position).per_name);
        Log.i("username------------>", hotTopicItemList.get(position).per_name);
        viewHolder.hot_title.setText(hotTopicItemList.get(position).hot_title);
        viewHolder.update_time
                .setText(hotTopicItemList.get(position).update_time);
        viewHolder.hot_content
                .setText(hotTopicItemList.get(position).hot_content);

        return convertView;
    }

    class ViewHolder {
        public ImageView ivIcon;
        public TextView per_name, userimgUrl, hot_content, hot_title,
                update_time;
        public Button hot_zan_btn, hot_pinlun_btn;
    }

    //Serializeable传递对象的方法
    public void SerializeMethod(int position){
        Intent intent=new Intent(mContext, HotCommentsDetailPage.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) ;

        HotTopicBean mHotTopicBean=new HotTopicBean();
        mHotTopicBean.setName(hotTopicItemList.get(position).per_name);
        mHotTopicBean.setCommentnum(hotTopicItemList.get(position).getCommentnum());
        mHotTopicBean.setCommentstr(hotTopicItemList.get(position).getCommentstr());
        mHotTopicBean.setFabulousnum(hotTopicItemList.get(position).getFabulousnum());
        mHotTopicBean.setHottitle(hotTopicItemList.get(position).getHottitle());
        mHotTopicBean.setUserimgUrl(hotTopicItemList.get(position).getUserimgUrl());
        mHotTopicBean.setTime(hotTopicItemList.get(position).getTime());
        mHotTopicBean.setContent(hotTopicItemList.get(position).getContent());

        Bundle mBundle = new Bundle();
        mBundle.putSerializable(SER_KEY,(Serializable) mHotTopicBean);
        intent.putExtras(mBundle);
        mContext.startActivity(intent);
    }

}

跳转后的activity主要代码:

// 数据显示出来
mHotTopicBean = (HotTopicBean) getIntent().getSerializableExtra(HotGameAdapter.SER_KEY); // 反序列化得到对象
hotdt_zan_btn.setText(mHotTopicBean.getFabulousnum() + "");
hotdt_pinlun_btn.setText(mHotTopicBean.getCommentnum() + "");


总结:

Android序列化对象主要有两种方法,实现Serializable接口、或者实现Parcelable接口。实现Serializable接口是JavaSE本身就支持的,而Parcelable是Android特有的功能,效率比实现Serializable接口高,而且还可以用在进程间通信(IPC)中。实现Serializable接口非常简单,声明一下就可以了。而实现Parcelable接口稍微复杂一些,但效率更高,推荐用这种方法提高性能。

至于选取哪种可参考下面的原则:
1.在使用内存的时候,Parcelable 类比Serializable性能高,所以推荐使用Parcelable类。(PM)
2.Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
3.Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。
尽管Serializable效率低点, 也不提倡用,但在这种情况下,还是建议你用Serializable 。(SS)


参考文章:

1. 序列化与反序列化总结(Serializable和Parcelable)

2. 【Android】Android中Serializable接口的定义和使用

你可能感兴趣的:(android开发经验)