先定一个小目标比如写一个QQ.docx

上传人:b****4 文档编号:5436468 上传时间:2022-12-16 格式:DOCX 页数:25 大小:23.14KB
下载 相关 举报
先定一个小目标比如写一个QQ.docx_第1页
第1页 / 共25页
先定一个小目标比如写一个QQ.docx_第2页
第2页 / 共25页
先定一个小目标比如写一个QQ.docx_第3页
第3页 / 共25页
先定一个小目标比如写一个QQ.docx_第4页
第4页 / 共25页
先定一个小目标比如写一个QQ.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

先定一个小目标比如写一个QQ.docx

《先定一个小目标比如写一个QQ.docx》由会员分享,可在线阅读,更多相关《先定一个小目标比如写一个QQ.docx(25页珍藏版)》请在冰豆网上搜索。

先定一个小目标比如写一个QQ.docx

先定一个小目标比如写一个QQ

先定一个小目标,比如写一个QQ

GitHub地址

QQDemo

项目简介

本项目是即时通讯的示例项目,使用了MVP模式,集成了环信SDK和Bmob后端云,展示了即时通讯基本的功能的实现,包括注册登录,退出登录,联系人列表,添加好友,删除好友,收发消息,消息提醒等功能。

使用的开源项目

BottomBar

EventBus

greenDAO

butterknife

学习目标

环信SDK的集成与使用

MVP模式的运用

ORM数据库的集成与使用

模块化思想的运用

即时通讯IM(InstantMessaging)

允许两人或多人使用网路即时的传递文字讯息、档案、语音与视频交流。

相关产品

鼻祖ICQ

国内主流QQ微信陌陌YY等

国外主流FacebookMessengerWhatsAppSkypeInstagramLine

第三方服务平台

环信

融云

网易云信

极光IM

腾讯云通信IM

爱萌

阿里悟空(2016年10月31号正式下线)

阿里百川云旺

环信

官网

即时通信云3.x文档easemob_business.png

环信集成

注册并创建应用

下载SDK

SDK的导入

SDK的初始化

.so文件夹

放在jniLibs

也可以放在libs目录下,不过需要在模块下的配置文件中配置

android{

sourceSets{

main{

jniLibs.srcDirs=['libs']

}

}

}

 

巨坑

运行出错:

Didn'tfindclass"com.hyphenate.chat.adapter.EMACallSession",原因是hyphenatechat_3.2.0.jar包内没有该类。

解决办法:

导入Demo源码中EaseUI库里面的hyphenatechat_3.2.0.jar替换。

软件架构

MVC

MVC应用于RubyonRails,SpringFramework,iOS开发和ASP.NET等。

Model:

获取数据的业务逻辑,网络操作,数据库操作

View:

UI

Controller:

操作Model层获取数据传递给UImvc.png

服务器端的MVCmvcpattern.png

Android中MVC

Android中并没有清晰的MVC框架,如果把Activity当做Controller,根据我们实际开发经验,里面会有大量的UI操作,所以V和C就傻傻分不清了。

Model:

JavaBean,NetworkManager,DataBaseHelper

View:

xmlres

Controller:

ActivityFragment

ArrayList-ListView-Adapter(MVC)

MVP

MVP主要应用于ASP.NET等。

MVP与MVC主要区别是View和Model不再耦合。

Model:

获取数据的业务逻辑,网络操作,数据库操作

View:

UI

Presenter:

操作Model层获取数据传递给UImvp.png

MVVM

MVVM主要应用于WPF,Silverlight,Caliburn,nRoute等。

Model:

获取数据的业务逻辑,网络操作,数据库操作

View:

UI

ViewModel:

将View和Model绑定mvvm.png

Android中MVVM

DataBindingLibrary

中文翻译

软件架构的核心思想

分层分模块architecture.png

参考

androidarchitecture

MVC,MVP和MVVM模式如何选择

UnderstandingMVC,MVPandMVVMDesignPatterns

教你认清MVC,MVP和MVVM

AndroidDataBinding

CleanArchitecture

准备好了么?

开车啦!

包的创建

adapter存放适配器

app存放常量类,Application类以及一些app层级的全局类

database数据库相关类

eventEventBus使用的事件类

factory工厂类

model数据模型

presenterMVP模型中的Presenter类

ui存放activity和fragment

utils工具类

viewMVP模型中的View类

widget自定义控件

基类的创建

BaseActivity

BaseFragment

Git初始化

Splash界面splash.png

功能需求

如果没有登录,延时2s,跳转到登录界面

如果已经登录,则跳转到主界面

MVP实现

SplashView

SplashPresenter

登录界面login.jpg

功能需求

有两种情况都可以发起登录操作,一是点击登录按钮,而是点击虚拟键盘上的Action键。

点击新用户,跳转到注册界面。

IMEOptions

注意配置EditText的imeOptions属性时,需要配合inputType才能起作用。

android:

imeOptions="actionNext"//下一个

android:

imeOptions="actionGo"//启动

android:

imeOptions="actionDone"//完成

android:

imeOptions="actionPrevious"//上一个

android:

imeOptions="actionSearch"//搜索

android:

imeOptions="actionSend"//发送

MVP实现

LoginView

LoginPresenter

EMCallBack的适配器

publicclassEMCallBackAdapterimplementsEMCallBack{

@Override

publicvoidonSuccess(){

}

@Override

publicvoidonError(inti,Strings){

}

@Override

publicvoidonProgress(inti,Strings){

}

}

Android6.0动态权限管理

介绍

举个栗子:

高德地图XX地图等

/**

*是否有写磁盘权限

*/

privatebooleanhasWriteExternalStoragePermission(){

intresult=ActivityCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE);

returnresult==PermissionChecker.PERMISSION_GRANTED;

}

/**

*申请权限

*/

privatevoidapplyPermission(){

String[]permissions={Manifest.permission.WRITE_EXTERNAL_STORAGE};

ActivityCompat.requestPermissions(this,permissions,REQUEST_WRITE_EXTERNAL_STORAGE);

}

/**

*申请权限回调

*/

@Override

publicvoidonRequestPermissionsResult(intrequestCode,@NonNullString[]permissions,@NonNullint[]grantResults){

switch(requestCode){

caseREQUEST_WRITE_EXTERNAL_STORAGE:

if(grantResults[0]==PermissionChecker.PERMISSION_GRANTED){

login();

}else{

toast(getString(R.string.not_get_permission));

}

break;

}

}

注册界面register.jpg

功能需求

用户名的长度必须是3-20位,首字母必须为英文字符,其他字符则除了英文外还可以是数字或者下划线。

密码必须是3-20位的数字。

密码和确认密码一致

正则表达式

正则表达式-元字符

privatestaticfinalStringUSER_NAME_REGEX="^[a-zA-Z]\\w{2,19}$";

privatestaticfinalStringPASSWORD_REGEX="^[0-9]{3,20}$";

\w匹配包括下划线的任何单词字符。

等价于'[A-Za-z0-9_]'。

MVP实现

RegisterView

RegisterPresenter

注册流程

实际项目中,注册会将用户名和密码注册到APP的服务器,然后APP的服务器再通过RESTAPI方式注册到环信服务器。

由于本项目没有APP服务器,会将用户数据注册到第三方云数据库Bmob,注册成功后,在客户端发送请求注册到环信服务器。

register_logic.png

云数据库

LeanCloud

Bmob

Parse(2017年1月28日关闭)

Bmob集成

开发文档

注册创建应用

下载SDK

导入SDK

初始化SDk

隐藏软键盘

protectedvoidhideSoftKeyboard(){

if(mInputMethodManager==null){

mInputMethodManager=(InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);

}

mInputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),0);

}

软键盘Action处理

privateTextView.OnEditorActionListenermOnEditorActionListener=newTextView.OnEditorActionListener(){

@Override

publicbooleanonEditorAction(TextViewv,intactionId,KeyEventevent){

if(actionId==EditorInfo.IME_ACTION_GO){

reigister();//注册

returntrue;

}

returnfalse;

}

};

用户名已注册的处理

Bmob错误码

主界面main.jpg

底部导航条

RadioGroup,TabHost,FragmentTabHost,自定义

第三方底部条

BottomBar

AHBottomNavigation

BottomNavigation

Fragment的切换

动态界面logout.jpg

联系人界面contact1.jpgcontact2.jpg

MVP实现

ContactView

ContactPresenter

RecyclerView的使用

CreatingListsandCards

联系人是否在同一个组

privatebooleanitemInSameGroup(inti,ContactItemitem){

returni>0&&(item.getFirstLetter()==mContactItems.get(i-1).getFirstLetter());

}

CardView的使用

SwipeRefreshLayout的使用

mSwipeRefreshLayout.setColorSchemeResources(R.color.qq_blue,R.color.qq_red);

mSwipeRefreshLayout.setOnRefreshListener(mOnRefreshListener);

自定义控件SlideBar

分类字符数组(供拷贝)

privatestaticfinalString[]SECTIONS={"A","B","C","D","E","F","G","H","I","J","K","L"

"M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};

绘制居中文本

在ContactFragment里面监听SlideBar的事件

privateSlideBar.OnSlideBarChangeListenermOnSlideBarChangeListener=newSlideBar.OnSlideBarChangeListener(){

@Override

publicvoidonSectionChange(intindex,Stringsection){

mSection.setVisibility(View.VISIBLE);

mSection.setText(section);

scrollToSection(section);

}

@Override

publicvoidonSlidingFinish(){

mSection.setVisibility(View.GONE);

}

};

/**

*RecyclerView滚动直到界面出现对应section的联系人

*

*@paramsection首字符

*/

privatevoidscrollToSection(Stringsection){

intsectionPosition=getSectionPosition(section);

if(sectionPosition!

=POSITION_NOT_FOUND){

mRecyclerView.smoothScrollToPosition(sectionPosition);

}

}

/**

*

*@paramsection首字符

*@return在联系人列表中首字符是section的第一个联系人在联系人列表中的位置

*/

privateintgetSectionPosition(Stringsection){

ListcontactItems=mContactListAdapter.getContactItems();

for(inti=0;i

if(section.equals(contactItems.get(i).getFirstLetterString())){

returni;

}

}

returnPOSITION_NOT_FOUND;

}

联系人点击事件

privateContactListAdapter.OnItemClickListenermOnItemClickListener=newContactListAdapter.OnItemClickListener(){

/**

*单击跳转到聊天界面

*@paramname点击item的联系人名字

*/

@Override

publicvoidonItemClick(Stringname){

startActivity(ChatActivity.class,Constant.Extra.USER_NAME,name);

}

/**

*长按删除好友

*@paramname点击item的联系人名字

*/

@Override

publicvoidonItemLongClick(finalStringname){

AlertDialog.Builderbuilder=newAlertDialog.Builder(getContext());

Stringmessage=String.format(getString(R.string.delete_friend_message),name);

builder.setTitle(getString(R.string.delete_friend))

.setMessage(message)

.setNegativeButton(getString(R.string.cancel),newDialogInterface.OnClickListener(){

@Override

publicvoidonClick(DialogInterfacedialog,intwhich){

dialog.dismiss();

}

})

.setPositiveButton(getString(R.string.confirm),newDialogInterface.OnClickListener(){

@Override

publicvoidonClick(DialogInterfacedialog,intwhich){

dialog.dismiss();

showProgress(getString(R.string.deleting_friend));

mContactPresenter.deleteFriend(name);

}

});

builder.show();

}

};

添加好友界面add_friend.jpg

搜索用户

查询数据

@Override

publicvoidsearchFriend(finalStringkeyword){

mAddFriendView.onStartSearch();

//注:

模糊查询只对付费用户开放,付费后可直接使用。

BmobQueryquery=newBmobQuery();

query.addWhereContains("username",keyword).addWhereNotEqualTo("username",EMClient.getInstance().getCurrentUser());

query.findObjects(newFindListener(){

@Override

publicvoiddone(Listlist,BmobExceptione){

processResult(list,e);

}

});

}

greenDAO

greenDAO是AndroidSQLite数据库ORM框架的一种。

ORM即对象关系映射,object/relationalmapping,将Java对象映射成数据库的表。

其他ORM框架

DBFlow

Ormlite

Sugar

ActiveAndroid

Sprinkles

Ollie

参考

Github

官网

AppBrain

使用文档

中文使用文档

创建实体类

@Entity

publicclassContact{

@Id

publicLongid;

publicStringuserName;

}

初始化

publicvoidinit(Contextcontext){

DaoMaster.DevOpenHelperdevOpenHelper=newDaoMaster.DevOpenHelper(context,Constant.Database.DATABASE_NAME,null);

SQLiteDatabasewritableDatabase=devOpenHelper.getWritableDatabase();

DaoMasterdaoMaster=newDaoMaster(writableDatabase);

mDaoSession=daoMaster.newSession();

}

保存联系人

publicvoidsaveContact(StringuserName){

Contactcontact=newContact();

contact.setUsername(userName);

mDaoSession.getContactDao().save(contact);

}

查询联系人

publicListqueryAllContacts(){

Listlist=mDaoSession.getContactDao().queryBuilder().list();

ArrayListcontacts=newArrayList();

for(inti=0;i

Stringcontact=list.get(i).getUsername();

contacts.add(contact);

}

returncontacts;

}

删除联系人

publicvoiddeleteAllContacts(){

ContactDaocontactDao=mDaoSession.getContactDao();

contactDao.deleteAll();

}

发送好友请求

AddFriendItemView里面处理点击事件

@OnClick(R.id.add)

publicvoidonClick(){

StringfriendName=mUserName.getText().toString().trim();

StringaddFriendReason=getContext().getString(R.string.add_friend_reason);

AddFriendEventevent=newAddFriendEvent(friendName,addFriendReason);

EventBus.getDefault().post(event);

}

AddFriendPresenterImpl实现发送好友请求

@Subscribe(threadMode=ThreadMode.BACKGROUND)

publicvoidaddFriend(AddFriendEventevent){

try{

EMClient.get

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 理化生

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1