开源学习 百度推送实战项目 友聊 (四)

来源:互联网 发布:gdi 高级编程 pdf版 编辑:程序博客网 时间:2024/05/24 05:50

这篇文章是 ”友聊“ 开源项目学习系列的第四篇,前三篇文章请查看这里:

友聊 学习记录(一)

友聊 学习记录(二)

友聊 学习记录 (三)


这篇文章里会主要记录项目中两个Fragment的使用,实现的功能。
先看下LeftFragment 的效果

图片说明文字

  1. 自定义的ExpandableListView ,项目中使用的开源控件IphoneTreeView。 关于ExpandableListView ,也可以参考之前在论坛里发的一个实例demo, 具体详情看这里
  2. 长按联系人,弹出QuickActionWidget , 继承Popwindow,定义了很多特性,上面的每个Button 都可以监听到,做出响应。
  3. 整个Layout,使用的是自定义的 HorizontalScrollView, 可以左右滑动,监听事件。项目中左右滑动会更新联系人,发出刷新的声音。

ExpandableListView 关键是在数据构造,事件的监听和响应。项目中处理点击事件,又添加了长按事件的监听,使用Tag区分GroupView 和ChildView ,做出不同的响应。

再看QuickActioinWidget 的相关操作

 1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132333435363738394041424344454647
// 显示子列表长按时弹窗private void showChildQuickActionBar(View view) {        mBar = new QuickActionBar(getActivity());        mBar.addQuickAction(new QuickAction(getActivity(),                R.drawable.ic_action_share_pressed, R.string.open));        mBar.addQuickAction(new QuickAction(getActivity(),                R.drawable.ic_action_rename_pressed, R.string.rename));        mBar.addQuickAction(new QuickAction(getActivity(),                R.drawable.ic_action_move_pressed, R.string.move));        mBar.addQuickAction(new QuickAction(getActivity(),                R.drawable.ic_action_delete_pressed, R.string.delete));        mBar.setOnQuickActionClickListener(mActionListener);        mBar.show(view);    }// QuickClickListener 的定义private OnQuickActionClickListener mActionListener = new OnQuickActionClickListener() {        public void onQuickActionClicked(QuickActionWidget widget, int position) {            User u = mChildren.get(mLongPressGroupId).get(mLongPressChildId);            if (u != null)                switch (position) {                case 0:                    mMsgDB.clearNewCount(u.getUserId());// 新消息置空                    Intent toChatIntent = new Intent(getActivity(),                            ChatActivity.class);                    toChatIntent.putExtra("user", u);                    startActivity(toChatIntent);                    break;                case 1:                    T.showShort(mApplication, "rename");                    break;                case 2:                    T.showShort(mApplication, "move");                    break;                case 3:                    mUserDB.delUser(u);                    updateAdapter();                    mRecentDB.delRecent(u.getUserId());                    ((MainActivity) getActivity()).upDateList();                    T.showShort(mApplication, "删除成功!");                    break;                default:                    break;                }        }    };

HorizontalScrollView 的使用很简单,都是在XML 中定义好相关的属性,实现左右滑动接口事件。

 1 2 3 4 5 6 7 8 9101112131415161718
 <com.way.pullrefresh.PullToRefreshHorizontalScrollView        xmlns:ptr="http://schemas.android.com/apk/res-auto"        android:id="@+id/pull_refresh_horizontalscrollview"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        ptr:ptrAnimationStyle="flip"        android:fillViewport="true"        ptr:ptrDrawable="@drawable/refresh_arrow_2"        ptr:ptrHeaderBackground="@drawable/coversation_bg_2"        ptr:ptrMode="both" >        <LinearLayout            android:layout_width="fill_parent"            android:layout_height="fill_parent"            android:orientation="horizontal" >              <include layout="@layout/main_left_fragment_content" />        </LinearLayout>    </com.way.pullrefresh.PullToRefreshHorizontalScrollView>

添加监听事件

 1 2 3 4 5 6 7 8 910111213141516
//不同的操作,响应不同的声音mSoundListener = new SoundPullEventListener(getActivity());        mSoundListener.addSoundEvent(State.PULL_TO_REFRESH, R.raw.pull_event);        mSoundListener.addSoundEvent(State.RESET, R.raw.reset_sound);        mSoundListener.addSoundEvent(State.REFRESHING, R.raw.refreshing_sound);// 刷新监听mPullRefreshScrollView                .setOnRefreshListener(new OnRefreshListener<HorizontalScrollView>() {                    @Override                    public void onRefresh(                            PullToRefreshBase<HorizontalScrollView> refreshView) {                        new GetDataTask().execute();                    }                });

这样LeftFragment 的只要功能基本完成了。接下来看RightFragment


先看下RightFragment 的效果图。

图片说明文字

普通的设置界面,也可以设计的很赞
这里使用了SlidingLayer,每一项点进去再回来,代码都很简单。有点类似ViewFlipper 的效果。若是我写,傻傻滴有要把每个页面都写成Fragment了。

设计接口,监听设置状态是否改变。

 1 2 3 4 5 6 7 8 9101112131415161718192021
@Override    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {        // TODO Auto-generated method stub        switch (buttonView.getId()) {        case R.id.message_notify_switch:            mSpUtil.setMsgNotify(isChecked);            break;        case R.id.message_sound_switch:            mSpUtil.setMsgSound(isChecked);            break;        case R.id.pullrefresh_sound_switch:            mSpUtil.setPullRefreshSound(isChecked);            listener.onSwitchChange(isChecked);            break;        case R.id.show_head_switch:            mSpUtil.setShowHead(isChecked);            break;        default:            break;        }    }

再看下SlidingLayer 的用法,SlidingLayer 有个接口OnInteractListener,有四个方法,open() ,close(), opened(),closed()

12345678
    // 打开layer的操作    case R.id.accountSetting:            mSlidingLayer.removeAllViews();            if (!mSlidingLayer.isOpened()) {                mSlidingLayer.addView(mAcountSetView);                mSlidingLayer.openLayer(true);            }            break;

RightFragment 的逻辑比较简单,没什么可说的。


接下来看Application类的设计

看下声明的字段,都知道干什么的了。

 1 2 3 4 5 6 7 8 91011121314151617181920
public static final int[] heads = { R.drawable.h0, R.drawable.h1,            R.drawable.h2, R.drawable.h3, R.drawable.h4, R.drawable.h5,            R.drawable.h6, R.drawable.h7, R.drawable.h8, R.drawable.h9,            R.drawable.h10, R.drawable.h11, R.drawable.h12, R.drawable.h13,            R.drawable.h14, R.drawable.h15, R.drawable.h16, R.drawable.h17,            R.drawable.h18 };    public static final int NUM_PAGE = 6;// 总共有多少页    public static int NUM = 20;// 每页20个表情,还有最后一个删除button    private static PushApplication mApplication;    private BaiduPush mBaiduPushServer;    private Map<String, Integer> mFaceMap = new LinkedHashMap<String, Integer>();    private SharePreferenceUtil mSpUtil;    private UserDB mUserDB;    private MessageDB mMsgDB;    private RecentDB mRecentDB;    private List<User> mUserList;    private MediaPlayer mMediaPlayer;    private NotificationManager mNotificationManager;    private Notification mNotification;    private Gson mGson;

需要使用的公共的全家变量放在这里,虽然这个方法知道的很多,作者使用的确实相当灵活,轻车熟路。

最后是CrashHandler 类的设计

直接看下代码

 1 2 3 4 5 6 7 8 910111213141516171819202122232425262728
public class CrashHandler implements UncaughtExceptionHandler {    private Thread.UncaughtExceptionHandler mDefaultHandler;// 系统默认的UncaughtException处理类    private static CrashHandler INSTANCE;// CrashHandler实例    private Context mContext;// 程序的Context对象    /** 保证只有一个CrashHandler实例 */    private CrashHandler() {    }    /** 获取CrashHandler实例 ,单例模式 */    public static CrashHandler getInstance() {        if (INSTANCE == null)            INSTANCE = new CrashHandler();        return INSTANCE;    }    /**     * 初始化     *      * @param context     */    public void init(Context context) {        mContext = context;        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();// 获取系统默认的UncaughtException处理器        Thread.setDefaultUncaughtExceptionHandler(this);// 设置该CrashHandler为程序的默认处理器    }

这个类的处理思路,在Application中实例化后,如果有没有处理的异常。

  1. 获取异常报告,包括app 信息,手机信息
  2. 将异常保存为文件
  3. 使用Email 发送报告

获取异常的代码

  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99100101102103104105106107108109110
/**     * 获取APP崩溃异常报告     *      * @param ex     * @return     */    private String getCrashReport(Context context, Throwable ex) {        PackageInfo pinfo = getPackageInfo(context);        StringBuffer exceptionStr = new StringBuffer();        exceptionStr.append("Version: " + pinfo.versionName + "("                + pinfo.versionCode + ")n");        exceptionStr.append("Android: " + android.os.Build.VERSION.RELEASE                + "(" + android.os.Build.MODEL + ")n");        exceptionStr.append("Exception: " + ex.getMessage() + "n");        StackTraceElement[] elements = ex.getStackTrace();        for (int i = 0; i < elements.length; i++) {            exceptionStr.append(elements[i].toString() + "n");        }        return exceptionStr.toString();    }// 将异常保存为文件private File save2File(String crashReport) {        // TODO Auto-generated method stub        String fileName = "crash-" + System.currentTimeMillis() + ".txt";        if (Environment.getExternalStorageState().equals(                Environment.MEDIA_MOUNTED)) {            try {                File dir = new File(Environment.getExternalStorageDirectory()                        .getAbsolutePath() + File.separator + "crash");                if (!dir.exists())                    dir.mkdir();                File file = new File(dir, fileName);                FileOutputStream fos = new FileOutputStream(file);                fos.write(crashReport.toString().getBytes());                fos.close();                return file;            } catch (Exception e) {                L.i("save2File error:" + e.getMessage());            }        }        return null;    }// 发送异常报告private void sendAppCrashReport(final Context context,            final String crashReport, final File file) {        // TODO Auto-generated method stub        AlertDialog dialog;        AlertDialog.Builder builder = new AlertDialog.Builder(context);        builder.setIcon(android.R.drawable.ic_dialog_info);        builder.setTitle(R.string.app_error);        builder.setMessage(R.string.app_error_message);        builder.setPositiveButton(R.string.submit_report,                new DialogInterface.OnClickListener() {                    public void onClick(DialogInterface dialog, int which) {                        try {                            Intent intent = new Intent(Intent.ACTION_SEND);                            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                            String[] tos = { "songyongqiang@kingsky-iot.com" };                            intent.putExtra(Intent.EXTRA_EMAIL, tos);                            intent.putExtra(Intent.EXTRA_SUBJECT,                                    "管车易APP客户端 - 错误报告");                            if (file != null) {                                intent.putExtra(Intent.EXTRA_STREAM,                                        Uri.fromFile(file));                                intent.putExtra(Intent.EXTRA_TEXT,                                        "请将此错误报告发送给我,以便我尽快修复此问题,谢谢合作!n");                            } else {                                intent.putExtra(Intent.EXTRA_TEXT,                                        "请将此错误报告发送给我,以便我尽快修复此问题,谢谢合作!n"                                                + crashReport);                            }                            intent.setType("text/plain");                            intent.setType("message/rfc882");                            Intent.createChooser(intent, "Choose Email Client");                            context.startActivity(intent);                        } catch (Exception e) {                            T.showLong(context,                                    "There are no email clients installed.");                        } finally {                            dialog.dismiss();                            // 退出                            android.os.Process.killProcess(android.os.Process                                    .myPid());                            System.exit(1);                        }                    }                });        builder.setNegativeButton(android.R.string.cancel,                new DialogInterface.OnClickListener() {                    public void onClick(DialogInterface dialog, int which) {                        dialog.dismiss();                        // 退出                        android.os.Process.killProcess(android.os.Process                                .myPid());                        System.exit(1);                    }                });        dialog = builder.create();        dialog.getWindow()                .setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);        dialog.show();    }

关于Fragment,Application ,以及CrashHandler 的学习就结束了。

下一篇,将接着学习 **友聊 ** 项目中Util 类 以及数据库相关的代码。

声明:eoe文章著作权属于作者,受法律保护,转载时请务必以超链接形式附带如下信息

原文作者: imesong

原文地址: http://my.eoe.cn/imesong/archive/21794.html


0 0
原创粉丝点击