目录
1、注册UI及验证逻辑实现
1.1 注册页面逻辑实现
1.2 验证效果
2、登录UI及验证逻辑实现
2.1 登录页面逻辑实现
2.2 验证效果
3、服务器数据简单介绍与基于GreenDao的数据库框架设计
3.1 使用Apache+PHP搭建服务器,读取本地的json数据
3.2 数据持久化--GreenDAO(使用单例模式确保操作唯一性)
3.3 登录、注册页面的信息持久化
4、用户状态与用户信息的回调封装
4.2 登录、注册成功回调--使用接口,进行解耦方便在功能模块实现自己的逻辑
4.3 回调方法的具体使用
4.4 验证回调方法
5、启动图界面与登录页面相关联
5.1 完善启动图页面逻辑
5.2 页面关联
注册登录的逻辑整理:
注册:首先判断注册的输入格式是否正确;点击注册按钮,将输入的信息以key-value形式保存在Params(参数名,参数值)中,获取本地准备好的用户信息保存到数据库中(此处与真实情况不符);设置登录成功标志位以及注册成功的提示。
登录:首先判断登录的输入格式是否正确;点击登录按钮,将输入的信息以key-value形式保存在Params(参数名,参数值)中,获取本地准备好的用户信息保存到数据库中(此处与真实情况不符);设置登录成功标志位以及登录成功的提示。
逻辑优化:
注册:首先判断注册的输入格式是否正确;点击注册按钮,需根据Params中的key判断电话号、邮箱、姓名是否被注册(包含相同信息可以Toast弹出提示信息,没有继续),将输入的信息以key-value形式保存在Params(<电话号,密码><邮箱,密码><姓名,密码>)中,将这些信息保存到数据库(手机内部的SQLite数据库,使用了GreenDao包装了)中。
登录:首先判断登录的输入格式是否正确;点击登录按钮,需根据Params中的key判断电话号、邮箱、姓名与对应保存的value密码是否相同(不相同以Toast弹出提示信息,相同则登录成功),不需要将信息保存到服务器的数据库中。
每次登陆注册是从Params中判断。但下次打开App,Params中数据清空(保存在内存中),需要先从数据库中将信息提取到Map中。然后进行登录注册判断。
1、注册UI及验证逻辑实现
1.1 注册页面逻辑实现
位于latte-ec模块sign包下的SignUpDelegate。
主要作用:注册页面的逻辑实现,包含:注册后保存用户信息,已经注册的用户跳转到登录页面。
public class SignUpDelegate extends LatteDelegate {@BindView(R2.id.edit_sign_up_name)TextInputEditText mName = null;@BindView(R2.id.edit_sign_up_email)TextInputEditText mEmail = null;@BindView(R2.id.edit_sign_up_phone)TextInputEditText mPhone = null;@BindView(R2.id.edit_sign_up_password)TextInputEditText mPassword = null;@BindView(R2.id.edit_sign_up_re_password)TextInputEditText mRePassword = null;@OnClick(R2.id.btn_sign_up)void onClickSignUp() {if (checkForm()) {Toast.makeText(getContext(), "验证通过", Toast.LENGTH_SHORT).show();}}@OnClick(R2.id.tv_link_sign_in)void onClickLink(){getSupportDelegate().start(new SignInDelegate());}public boolean checkForm() {//检查填入的信息是否正确final String name = mName.getText().toString();final String email = mEmail.getText().toString();final String phone = mPhone.getText().toString();final String password = mPassword.getText().toString();final String rePassword = mRePassword.getText().toString();boolean isPass = true;if (name.isEmpty()) {mName.setError("请输入姓名");isPass = false;} else {mName.setError(null);}if (email.isEmpty() || !Patterns.EMAIL_ADDRESS.matcher(email).matches()) {mEmail.setError("错误的邮箱格式");isPass = false;} else {mEmail.setError(null);}if (phone.isEmpty() || phone.length() != 11) {mPhone.setError("手机号码错误");isPass = false;} else {mPhone.setError(null);}if (password.isEmpty() || password.length() < 6) {mPassword.setError("请填写至少6位数密码");isPass = false;} else {mPassword.setError(null);}if (rePassword.isEmpty() || rePassword.length() < 6 || !(rePassword.equals(password))) {mRePassword.setError("密码验证错误");isPass = false;} else {mRePassword.setError(null);}return isPass;}@Overridepublic Object setLayout() {return R.layout.delegate_sign_up;}@Overridepublic void onBindView(@Nullable Bundle savedInstanceState, View rootView) {}
}
1.2 验证效果
在example模块下,ExampleActivity类中,将根Fragment替换为注册图界面。
public class ExampleActivity extends ProxyActivity {@Overridepublic LatteDelegate setRootDelegate() {return new SignUpDelegate();}
}
2、登录UI及验证逻辑实现
2.1 登录页面逻辑实现
位于latte-ec模块sign包下的SignInDelegate。
主要作用:登录页面的逻辑实现,包含:登录后保存用户信息,还未注册的用户跳转到注册页面。
public class SignInDelegate extends LatteDelegate {@BindView(R2.id.edit_sign_in_email)TextInputEditText mEmail = null;@BindView(R2.id.edit_sign_in_password)TextInputEditText mPassword = null;@OnClick(R2.id.btn_sign_in)void onClickSignIn(){if (checkForm()){Toast.makeText(getContext(), "验证通过", Toast.LENGTH_SHORT).show();}}@OnClick(R2.id.icon_sign_in_wechat)void onClickWeChat(){//微信登录逻辑}@OnClick(R2.id.tv_link_sign_up)void onClickLink(){//未注册的,跳转到注册页面getSupportDelegate().start(new SignUpDelegate());}public boolean checkForm() {//检查填入信息final String email = mEmail.getText().toString();final String password = mPassword.getText().toString();boolean isPass = true;if (email.isEmpty() || !Patterns.EMAIL_ADDRESS.matcher(email).matches()) {mEmail.setError("错误的邮箱格式");isPass = false;} else {mEmail.setError(null);}if (password.isEmpty() || password.length() < 6) {mPassword.setError("请填写至少6位数密码");isPass = false;} else {mPassword.setError(null);}return isPass;}@Overridepublic Object setLayout() {return R.layout.delegate_sign_in;}@Overridepublic void onBindView(@Nullable Bundle savedInstanceState, View rootView) {}
}
2.2 验证效果
在example模块下,ExampleActivity类中,将根Fragment替换为登录图界面。
public class ExampleActivity extends ProxyActivity {@Overridepublic LatteDelegate setRootDelegate() {return new SignInDelegate();}
}
3、服务器数据简单介绍与基于GreenDao的数据库框架设计
3.1 使用Apache+PHP搭建服务器,读取本地的json数据
使用php对json数据进行了包装,最终在代码中通过获取.php文件来读取本地json数据
<?php
$file_name = 'http://127.0.0.1:8081/RestServer/data/user_profile.json';//获取的本地json数据
$file = file_get_contents($file_name);
echo $file;
开启Apache服务,在浏览器中输入:http://192.168.56.1:8081/RestServer/api/user_profile.php(前面是本机ip地址,可通过cmd查询;8081是自己更改的端口号),可以获取到json数据信息。
3.2 数据持久化--GreenDAO(使用单例模式确保操作唯一性)
配置GreenDAO依赖
位于latte-ec模块database包下的UserProfile。
主要作用:实体类,一个实体类代表一张表,里面包含表中各个字段。
@Entity(nameInDb = "user_profile")//定义实体类,nameInDb:数据库名
public class UserProfile {@Idprivate long userId = 0;//唯一id,必须是long型private String name = null;private String avatar = null;private String gender = null;private String address = null;
}
Rebuild Project后会在UserProfile类后自动生成对各个字段得get、set方法。以及自动生成DaoMaster、DaoSession、UserProfileDao文件。
DaoMaster:GreenDao的框架管理类,该类对数据库相关管理进行了封装。
内部含有OpenHelper类(继承于SQLiteOpenHelper)创建所有的数据库;内部有Map集合,将每个EntityDao对象的字节码与它的数据库建立映射关系。通过Map管理所有的EntityDao类(每个类相当于一张表)。
DaoSession:链接GreenDao到SQLite数据库的纽带,通过它可以得到一个与数据库某张表相关的操作对象EntityDao。
从DaoMaster的Map集合中通过key(EntityDao.class)获取到管理数据库的对象(DaoConfig),传递给EntityDao类。DaoSession中的CRUD都是通过调用EntityDao进行的。
UserProfileDao:是具体的EntityDao类,有生成器生成的数据库操作类,封装了所有对数据库表进行CRUD的方法。
位于latte-ec模块database包下的ReleaseOpenHelper,继承自DaoMaster.OpenHelper。
主要作用:数据库表生成类,对DaoMaster自带的OpenHelper进行了封装。
public class ReleaseOpenHelper extends DaoMaster.OpenHelper {public ReleaseOpenHelper(Context context, String name) {super(context, name);}public ReleaseOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {super(context, name, factory);}@Overridepublic void onCreate(Database db) {super.onCreate(db);}
}
位于latte-ec模块database包下的DatabaseManager。
主要作用:数据库的管理类,内部初始化DaoMaster(使用单例,确保线程安全),内含获取到EntityDao对象的方法。
public class DatabaseManager {private DaoSession mDaoSession = null;private UserProfileDao mDao = null;private DatabaseManager() {}public DatabaseManager init(Context context) {initDao(context);return this;}private static final class Holder {//静态内部类单例模式private static final DatabaseManager INSTANCE = new DatabaseManager();}public static DatabaseManager getInstance() {return Holder.INSTANCE;}private void initDao(Context context) {final ReleaseOpenHelper helper = new ReleaseOpenHelper(context, "fast_ec.db");//传入数据库名,在Map集合中与对应的实体类建立映射关系final Database db = helper.getWritableDb();//以读写方式得到数据库mDaoSession = new DaoMaster(db).newSession();mDao = mDaoSession.getUserProfileDao();//获取该数据库的实体类操作对象}public final UserProfileDao getDao() {return mDao;}
}
在example模块下的ExampleApp类中进行数据库初始化。
public class exampleApp extends Application {@Overridepublic void onCreate() {super.onCreate();Latte.init(this).......configure();
** DatabaseManager.getInstance().init(this);//初始化数据库}
}
3.3 登录、注册页面的信息持久化
位于latte-ec模块database包下的SignHandler。
主要作用:通过登录、注册成功后,获取到已经准备好的json数据,读取json数据保存到数据库中;并设置登录、注册状态以及成功的回调。
public class SignHandler {public static void onSignIn(String response,ISignListener signListener) {final JSONObject profileJson = JSON.parseObject(response).getJSONObject("data");final long userId = profileJson.getLong("userId");final String name = profileJson.getString("name");final String avatar = profileJson.getString("avatar");final String gender = profileJson.getString("gender");final String address = profileJson.getString("address");final UserProfile profile = new UserProfile(userId, name, avatar, gender, address);//从JSON中获取数据,插入数据库DatabaseManager.getInstance().getDao().insert(profile);//将数据插入数据库//已经注册并成功登录AccountManager.setSignState(true);signListener.onSignInSuccess();}public static void onSignUp(String response,ISignListener signListener) {final JSONObject profileJson = JSON.parseObject(response).getJSONObject("data");final long userId = profileJson.getLong("userId");final String name = profileJson.getString("name");final String avatar = profileJson.getString("avatar");final String gender = profileJson.getString("gender");final String address = profileJson.getString("address");final UserProfile profile = new UserProfile(userId, name, avatar, gender, address);DatabaseManager.getInstance().getDao().insert(profile);//已经注册并成功登录AccountManager.setSignState(true);signListener.onSignUpSuccess();}
}
位于latte-ec模块sign包下的SignUpDelegate。完善注册成功后的保存数据到数据库
主要作用:注册页面的逻辑实现,包含:注册后保存用户信息,已经注册的用户跳转到登录页面。
@OnClick(R2.id.btn_sign_up)void onClickSignUp() {if (checkForm()) {RestClient.builder().url("http://192.168.50.189:8081/RestServer/api/user_profile.php").params("name",mName.getText().toString()).params("email", mEmail.getText().toString()).params("phone",mPhone.getText().toString()).params("password",mPassword.getText().toString()).success(new ISuccess() {@Overridepublic void onSuccess(String response) {LatteLogger.json("USER_PROFILE", response);SignHandler.onSignUp(response, mISignListener);}}).build().post();}}
位于latte-ec模块sign包下的SignInDelegate。完善登录成功后的保存数据到数据库
主要作用:登录页面的逻辑实现,包含:登录后保存用户信息,还未注册的用户跳转到注册页面。
@OnClick(R2.id.btn_sign_in)void onClickSignIn(){if (checkForm()){RestClient.builder().url("http://192.168.1.103:8081/RestServer/api/user_profile.php").params("email", mEmail.getText().toString()).params("password",mPassword.getText().toString()).success(new ISuccess() {@Overridepublic void onSuccess(String response) {LatteLogger.json("USER_PROFILE", response);SignHandler.onSignIn(response, mISignListener);}}).build().post();}}
通过adb shell查看数据库信息
4、用户状态与用户信息的回调封装
4.1 用户状态回调--sharedPreference
位于latte-core模块app包下的IUserChecker接口。
主要作用:两个方法:登录、未登录。
public interface IUserChecker {void onSignIn();void onNotSignIn();
}
位于latte-core模块app包下的AccountManager。
主要作用:管理用户信息,内部通过sharedPreference保存登陆状态,检查用户状态--回调IUserChecker接口中方法。
public class AccountManager {private enum SignTag{SIGN_TAG}//保存用户登录状态,登录后调用public static void setSignState(boolean state){LattePreference.setAppFlag(SignTag.SIGN_TAG.name(), state);}private static boolean isSignIn(){return LattePreference.getAppFlag(SignTag.SIGN_TAG.name());}public static void checkAccount(IUserChecker checker){//检查登陆状态if (isSignIn()){checker.onSignIn();}else {checker.onNotSignIn();}}
}
4.2 登录、注册成功回调--使用接口,进行解耦方便在功能模块实现自己的逻辑
位于latte-ec模块sign包下的ISignListener接口。
主要作用:两个方法:登录成功、注册成功。
public interface ISignListener {void onSignInSuccess();void onSignUpSuccess();
}
4.3 回调方法的具体使用
位于latte-ec模块sign包下的SignUpDelegate。完善注册成功后的的信息回调
主要作用:注册页面的逻辑实现,包含:注册后保存用户信息,已经注册的用户跳转到登录页面。
SignInDelegate添加了与SignUpDelegate相同的代码。
public class SignUpDelegate extends LatteDelegate {private ISignListener mISignListener = null;@Overridepublic void onAttach(Activity activity) {super.onAttach(activity);if (activity instanceof ISignListener){mISignListener = (ISignListener) activity;//确保只有继承ISignListener的activity才能实现该方法}}@OnClick(R2.id.btn_sign_up)void onClickSignUp() {if (checkForm()) {RestClient.builder()....success(new ISuccess() {@Overridepublic void onSuccess(String response) {LatteLogger.json("USER_PROFILE", response);
** SignHandler.onSignUp(response, mISignListener);}}).build().post();}}
}
位于latte-ec模块database包下的SignHandler。完善登录、注册状态以及成功的回调。
主要作用:通过登录、注册成功后,获取到已经准备好的json数据,读取json数据保存到数据库中;并设置登录、注册状态以及成功的回调。
public class SignHandler {public static void onSignIn(String response,ISignListener signListener) {......//已经注册并成功登录AccountManager.setSignState(true);signListener.onSignInSuccess();}public static void onSignUp(String response,ISignListener signListener) {......//已经注册并成功登录AccountManager.setSignState(true);signListener.onSignUpSuccess();}
}
4.4 验证回调方法
在example模块下,ExampleActivity类中,实现ISignListener接口中登陆成功、注册成功的方法。
@Overridepublic void onSignInSuccess() {Toast.makeText(this,"登录成功",Toast.LENGTH_LONG).show();}@Overridepublic void onSignUpSuccess() {Toast.makeText(this,"注册成功",Toast.LENGTH_LONG).show();}
5、启动图界面与登录页面相关联
当启动后,判断用户是否登录?登录了:直接跳到主界面;没登陆:跳转到登录界面。(是否登录了?已经在AccountManager中通过SharedPreference保存了)
5.1 完善启动图页面逻辑
位于latte-ui模块launcher包下的ILauncherListener接口。
主要作用:登陆状态判断的回调,在里面设置是否登陆的标志位,最后根据登录标记位判断打开的Fragment
登录过:直接打开主页;没登陆:跳到登录界面。
public interface ILauncherListener {void onLauncherFinish(OnLauncherFinishTag tag);//登录后回调,传入登陆状态
}
位于latte-ec模块launcher包下的LauncherDelegate类,完善启动后登录逻辑的判断。
主要作用:启动页面的逻辑。
public class LauncherDelegate extends LatteDelegate implements ITimerListener {private ILauncherListener mILauncherListener = null;@Overridepublic void onAttach(Activity activity) {//初始化接口实例:实现ILauncherListener接口的activitysuper.onAttach(activity);if (activity instanceof ILauncherListener){mILauncherListener = (ILauncherListener) activity;}}//判断是否显示滑动启动页private void checkIsShowScroll(){if (!LattePreference.getAppFlag(ScrollLauncherTag.HAS_FIRST_LAUNCHER_APP.name())){getSupportDelegate(). start(new LauncherScrollDelegate(), SINGLETASK);}else {//检查用户是否登陆了APPAccountManager.checkAccount(new IUserChecker() {@Overridepublic void onSignIn() {if (mILauncherListener!=null){mILauncherListener.onLauncherFinish(OnLauncherFinishTag.SIGNED);//设置登录的标志位}}@Overridepublic void onNotSignIn() {if (mILauncherListener!=null){mILauncherListener.onLauncherFinish(OnLauncherFinishTag.NOT_SIGNED);}}});}}
}
5.2 页面关联
在example模块下,ExampleActivity类中,实现ILauncherListener接口,完成登陆状态判断方法:根据标记位:登录过:直接打开主页;没登陆:跳到登录界面。
@Overridepublic void onLauncherFinish(OnLauncherFinishTag tag) {switch (tag){case SIGNED:Toast.makeText(this,"启动结束,用户登录了",Toast.LENGTH_LONG).show();getSupportDelegate().startWithPop(new EcBottomDelegate());break;case NOT_SIGNED:Toast.makeText(this,"启动结束,用户没登录",Toast.LENGTH_LONG).show();getSupportDelegate().startWithPop(new SignInDelegate());break;default:break;}}