在上一篇博客中完成了新闻详情数据的查看以及用户的注册登录,这篇文章中将对用户的信息进行增加和修改。会使用到文件读写、相机权限、自定义Dialog、相册选取和相机拍照。
===============================================================
下面先进行数据库的升级,因为我们要更换用户的头像,因此首先用户表里面是需要一个头像的字段的,之前对数据库进行升级的时候都是直接添加一个表,那么这一次升级我们往表里面增加一个字段。
一般来说再设计数据库的时候就要想到一些因素,像增加表字段这种事情一般是出现在业务需求有改动的情况下,因此我们在设计表的时候可以想清楚有没有可能进行扩展,会怎样扩展。下面我们要往数据表User中增加一个avatar的字段,表示头像。
同时,增加get和set方法。
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
然后进行数据库的升级,打开AppDatabase,增加如下代码:
/**
- 版本升级迁移到5 在用户表中新增一个avatar字段
*/
static final Migration MIGRATION_4_5 = new Migration(4, 5) {
@Override
public void migrate(@NonNull @NotNull SupportSQLiteDatabase database) {
//User表中新增avatar字段
database.execSQL(“ALTER TABLE user
ADD COLUMN avatar TEXT”);
}
};
这表示我在User表中增加一个avatar字段,然后我们添加迁移
再把数据库版本改成5。
这样,数据库的升级迁移就完成了。
UserRepository中的代码也需要更新,在里面增加如下代码:
private static volatile UserRepository mInstance;
public static UserRepository getInstance() {
if (mInstance == null) {
synchronized (UserRepository.class) {
if (mInstance == null) {
mInstance = new UserRepository();
}
}
}
return mInstance;
}
这一篇文章中将会涉及到HomeActivity中的页面数据交互,因此,我们需要一个HomeViewModel,在viewmodels包下创建它,里面的代码如下:
public class HomeViewModel extends BaseViewModel {
public LiveData user;
public String defaultName = “初学者-Study”;
public String defaultIntroduction = “Android | Java”;
public void getUser() {
user = UserRepository.getInstance().getUser();
}
public void updateUser(User user) {
UserRepository.getInstance().updateUser(user);
failed = UserRepository.getInstance().failed;
getUser();
}
}
这里我放置了两个默认值,因为在注册的时候,昵称和简介是可以不用填写的,所以在显示的时候如果没有填就显示这个默认值,如果是Kotlin的话就直接使用缺省值就好了,这两个默认值会在xml中用到的。同时这个HomeViewModel里面有一个获取用户信息和修改用户信息的方法,当我们登录成功进入的HomeActivity时是获取,当修改用户信息的时候是更新,这很好理解。这一步说清楚之后下面就要做新的操作了。
下面要定义一个dialog,用于App中使用,在view包下新建一个dialog包,包下新建一个DialogViewHelper类,里面的代码如下:
① DialogViewHelper
public class DialogViewHelper {
private View mContentView;
private SparseArray<WeakReference> mViews;
public DialogViewHelper(Context context, int layoutResId) {
this();
mContentView = LayoutInflater.from(context).inflate(layoutResId, null);
}
public DialogViewHelper() {
mViews = new SparseArray<>();
}
public void setText(int viewId, CharSequence text) {
TextView tv = getView(viewId);
if (tv != null) {
tv.setText(text);
}
}
public T getView(int viewId) {
WeakReference weakReference = mViews.get(viewId);
View view = null;
if (weakReference != null) {
view = weakReference.get();
}
if (view == null) {
view = mContentView.findViewById(viewId);
if (view != null) {
mViews.put(viewId, new WeakReference<>(view));
}
}
return (T) view;
}
public void setOnClickListener(int viewId, View.OnClickListener onClickListener) {
View view = getView(viewId);
if (view != null) {
view.setOnClickListener(onClickListener);
}
}
public void setIcon(int viewId, int resId) {
ImageView iv = getView(viewId);
if (iv != null) {
iv.setImageResource(resId);
}
}
public void setContentView(View contentView) {
mContentView = contentView;
}
public View getContentView() {
return mContentView;
}
}
② AlertController
同样在dialog包下新建一个AlertController类,代码如下:
public class AlertController {
private AlertDialog mAlertDialog;
private Window mWindow;
private DialogViewHelper mViewHelper;
public AlertController(AlertDialog alertDialog, Window window) {
mAlertDialog = alertDialog;
mWindow = window;
}
public void setDialogViewHelper(DialogViewHelper dialogViewHelper) {
mViewHelper = dialogViewHelper;
}
public void setText(int viewId, CharSequence text) {
mViewHelper.setText(viewId, text);
}
public void setIcon(int viewId, int resId) {
mViewHelper.setIcon(viewId, resId);
}
public T getView(int viewId) {
return mViewHelper.getView(viewId);
}
public void setOnClickListener(int viewId, View.OnClickListener onClickListener) {
mViewHelper.setOnClickListener(viewId, onClickListener);
}
public AlertDialog getDialog() {
return mAlertDialog;
}
public Window getWindow() {
return mWindow;
}
//-------------------------------------------------------------------------------------------------
public static class AlertParams {
public Context mContext;
//对话框主题背景
public int mThemeResId;
public boolean mCancelable;
public DialogInterface.OnCancelListener mOnCancelListener;
public DialogInterface.OnDismissListener mOnDismissListener;
public DialogInterface.OnKeyListener mOnKeyListener;
//文本颜色
public SparseArray mTextColorArray = new SparseArray<>();
//存放文本的更改
public SparseArray mTextArray = new SparseArray<>();
//存放点击事件
public SparseArray<View.OnClickListener> mClickArray = new SparseArray<>();
//存放长按点击事件
public SparseArray<View.OnLongClickListener> mLondClickArray = new SparseArray<>();
//存放对话框图标
public SparseArray mIconArray = new SparseArray<>();
//存放对话框图片
public SparseArray mBitmapArray = new SparseArray<>();
//对话框布局资源id
public int mLayoutResId;
//对话框的view
public View mView;
//对话框宽度
public int mWidth;
//对话框高度
public int mHeight;
//对话框垂直外边距
public int mHeightMargin;
//对话框横向外边距
public int mWidthMargin;
//动画
public int mAnimation;
//对话框显示位置
public int mGravity = Gravity.CENTER;
public AlertParams(Context context, int themeResId) {
mContext = context;
mThemeResId = themeResId;
}
public void apply(AlertController alert) {
//设置对话框布局
DialogViewHelper dialogViewHelper = null;
if (mLayoutResId != 0) {
dialogViewHelper = new DialogViewHelper(mContext, mLayoutResId);
}
if (mView != null) {
dialogViewHelper = new DialogViewHelper();
dialogViewHelper.setContentView(mView);
}
if (dialogViewHelper == null) {
throw new IllegalArgumentException(“please set layout”);
}
//将对话框布局设置到对话框
alert.getDialog().setContentView(dialogViewHelper.getContentView());
//设置DialogViewHelper辅助类
alert.setDialogViewHelper(dialogViewHelper);
//设置文本
for (int i = 0; i < mTextArray.size(); i++) {
alert.setText(mTextArray.keyAt(i), mTextArray.valueAt(i));
}
//设置图标
for (int i = 0; i < mIconArray.size(); i++) {
alert.setIcon(mIconArray.keyAt(i), mIconArray.valueAt(i));
}
//设置点击
for (int i = 0; i < mClickArray.size(); i++) {
alert.setOnClickListener(mClickArray.keyAt(i), mClickArray.valueAt(i));
}
//配置自定义效果,底部弹出,宽高,动画,全屏
Window window = alert.getWindow();
window.setGravity(mGravity);//显示位置
if (mAnimation != 0) {
window.setWindowAnimations(mAnimation);//设置动画
}
//设置宽高
WindowManager.LayoutParams params = window.getAttributes();
params.width = mWidth;
params.height = mHeight;
params.verticalMargin = mHeightMargin;
params.horizontalMargin = mWidthMargin;
window.setAttributes(params);
}
}
}
下面自定义Dialog
③ AlertDialog
在dialog包下新建一个AlertDialog,里面的代码如下:
public class AlertDialog extends Dialog {
private AlertController mAlert;
public AlertDialog(@NonNull Context context, @StyleRes int themeResId) {
super(context, themeResId);
mAlert = new AlertController(this, getWindow());
}
public void setText(int viewId, CharSequence text) {
mAlert.setText(viewId, text);
}
public T getView(int viewId) {
return mAlert.getView(viewId);
}
public void setOnClickListener(int viewId, View.OnClickListener onClickListener) {
mAlert.setOnClickListener(viewId, onClickListener);
}
//----------------------------------------------------------------------------------------------
public static class Builder {
private final AlertController.AlertParams P;
public Builder(Context context) {
this(context, R.style.dialog);
}
public Builder(Context context, int themeResId) {
P = new AlertController.AlertParams(context, themeResId);
}
/**
-
设置对话框布局
-
@param view
-
@return
*/
public Builder setContentView(View view) {
P.mView = view;
P.mLayoutResId = 0;
return this;
}
/**
-
@param layoutId
-
@return
*/
public Builder setContentView(int layoutId) {
P