概述
对于很多具有个人账户体系的Android应用程序,都需要用户修改个人信息,比如头像、昵称、性别等等。本文将详细介绍如何在Android应用中开发修改个人信息的功能。
实现原理
要实现修改个人信息的功能,首先需要考虑如何存储用户的信息。我们可以使用本地存储和远程服务器存储两种方式。
本地存储方式是将用户信息保存在客户端设备上的本地数据库或者SharedPreferences中。使用SQLite数据库,可以创建一个UserInfo表,并在其中添加用户名、头像、昵称、性别等字段,然后将用户的个人信息存储在该表中。要修改个人信息,只需要对该表进行更新即可。
远程服务器存储方式是将用户信息保存在服务器上,通常是通过网络请求进行操作。我们可以使用后端框架,比如SpringMVC搭建一个服务器程序,将用户信息保存在数据库中。
具体实现方案
本地存储方案
1.创建数据库
创建一个SQLite数据库,并在其中创建一个UserInfo表,该表包含UserName、Avatar、NickName、Gender四个字段。
首先在app/build.gradle中添加下面的依赖项,以便使用SQLite数据库。
```
dependencies {
implementation 'com.android.support:support-core-utils:28.0.0'
implementation 'com.j256.ormlite:ormlite-android:5.1'
implementation 'com.j256.ormlite:ormlite-core:5.1'
}
```
然后创建一个DatabaseHelper类,实现或者扩展OrmLiteSqliteOpenHelper类。
```
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static final String DATABASE_NAME = "UserInfo.db";
private static final int DATABASE_VERSION = 1;
private Dao
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource) {
try {
TableUtils.createTable(connectionSource, UserInfo.class);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, ConnectionSource connectionSource, int i, int i1) {
try {
TableUtils.dropTable(connectionSource, UserInfo.class, true);
onCreate(sqLiteDatabase, connectionSource);
} catch (SQLException e) {
e.printStackTrace();
}
}
public Dao
if (userInfoDao == null) {
userInfoDao = getDao(UserInfo.class);
}
return userInfoDao;
}
}
```
这里使用OrmLiteSqliteOpenHelper来创建SQLite数据库,并提供数据库升级和降级的功能。
2.创建用户信息实体和查询和修改方法
接着创建UserInfo实体类,以及操作数据库的方法。以下是UserInfo类的示例:
```
@DatabaseTable(tableName = "UserInfo")
public class UserInfo {
@DatabaseField(generatedId = true)
private int id;
@DatabaseField(columnName = "UserName")
private String userName;
@DatabaseField(columnName = "Avatar")
private String avatar;
@DatabaseField(columnName = "NickName")
private String nickName;
@DatabaseField(columnName = "Gender")
private String gender;
public UserInfo() {
}
public UserInfo(int id, String userName, String avatar, String nickName, String gender) {
this.id = id;
this.userName = userName;
this.avatar = avatar;
this.nickName = nickName;
this.gender = gender;
}
// getter和setter方法省略
}
```
使用这个类来查询和修改用户的个人信息。
查询用户信息:
```
public UserInfo queryUserInfo(Context context, String userName) {
try {
DatabaseHelper helper = new DatabaseHelper(context);
Dao
UserInfo userInfo = userInfoDao.queryBuilder().where().eq("UserName", userName).queryForFirst();
helper.close();
return userInfo;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
```
修改用户信息:
```
public boolean updateUserInfo(Context context, String userName, String avatar, String nickName, String gender) {
try {
DatabaseHelper helper = new DatabaseHelper(context);
Dao
UpdateBuilder
updateBuilder.updateColumnValue("Avatar", avatar);
updateBuilder.updateColumnValue("NickName", nickName);
updateBuilder.updateColumnValue("Gender", gender);
updateBuilder.where().eq("UserName", userName);
int numOfRowsAffected = updateBuilder.update(); //修改行
helper.close();
return numOfRowsAffected > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
```
可以看到这个方法将头像、昵称和性别更新到了数据库中,接着调用updateBuilder.update()方法来进行信息更新操作。
3.创建修改个人信息的界面
接下来,我们需要在应用中创建一个修改个人信息的界面。该界面包含UserName输入框、Avatar显示区(可以点击修改)、NickName输入框、Gender选择框等。
我们可以使用Android中的LinearLayout、RelativeLayout、TextView、EditText、ImageView等控件来创建布局。将修改个人信息的界面布局放在activity_modify_user_info.xml文件中。
4.修改个人信息界面的逻辑代码
创建ModifyUserInfoActivity文件,并在该文件中声明常量和变量。实现下面的代码:
```
public class ModifyUserInfoActivity extends AppCompatActivity {
private static final int REQUEST_CODE_PICK_PHOTO = 1; // 请求码——选择图片
private static final int REQUEST_CODE_TAKE_PHOTO = 2; // 请求码——拍照
private ImageView ivAvatar; // 头像显示区
private EditText etUserName; // 用户名输入框
private EditText etNickName; // 昵称输入框
private Button btnTakePhoto; // 选择拍照的按钮
private Button btnPickPhoto; // 选择图片的按钮
private RadioGroup rgGender; // 性别单选组
private String mBase64Avatar; // base64格式的头像
private String mUserName; // 用户名
private String mNickName; // 昵称
private String mGender; // 性别
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_modify_user_info);
ivAvatar = findViewById(R.id.ivAvatar);
etUserName = findViewById(R.id.etUserName);
etNickName = findViewById(R.id.etNickName);
btnTakePhoto = findViewById(R.id.btnTakePhoto);
btnPickPhoto = findViewById(R.id.btnPickPhoto);
rgGender = findViewById(R.id.rgGender);
// 添加头像点击事件
ivAvatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showPickPhotoDialog();
}
});
// 添加拍照按钮点击事件
btnTakePhoto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openCamera();
}
});
// 添加选择相册图片按钮点击事件
btnPickPhoto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pickPhoto();
}
});
// 添加性别单选组选择事件
rgGender.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId == R.id.rbMale) {
mGender = "男";
} else if (checkedId == R.id.rbFemale) {
mGender = "女";
}
}
});
// 获取当前用户信息并显示
SharedPreferences sp = getSharedPreferences("userInfo", MODE_PRIVATE);
mUserName = sp.getString("UserName", "");
UserInfo userInfo = queryUserInfo(this, mUserName);
mBase64Avatar = userInfo.getAvatar();
mNickName = userInfo.getNickName();
mGender = userInfo.getGender();
etUserName.setText(mUserName);
ivAvatar.setImageBitmap(Utils.decodeBase64(mBase64Avatar));
etNickName.setText(mNickName);
if (mGender.equals("男")) {
rgGender.check(R.id.rbMale);
} else if (mGender.equals("女")) {
rgGender.check(R.id.rbFemale);
}
}
/**
* 保存按钮点击事件
* 在本地数据库中更新用户信息
*/
public void onSaveBtnClicked(View view) {
String avatar = mBase64Avatar;
String nickName = etNickName.getText().toString();
String gender = mGender;
if (updateUserInfo(this, mUserName, avatar, nickName, gender)) {
Toast.makeText(this, "修改成功!", Toast.LENGTH_SHORT).show();
finish();
} else {
Toast.makeText(this, "修改失败!", Toast.LENGTH_SHORT).show();
}
}
}
```
在这个代码中,我们绑定了头像显示区、用户名、昵称、性别的显示控件,使用SharedPreferences获取当前登录的用户名。获取到当前用户名之后,我们使用queryUserInfo()方法从本地数据库中获取当前用户信息。然后修改头像、用户昵称、性别信息并保存至本地数据库中。
我们还为头像区添加了点击事件,使用showPickPhotoDialog()方法展示Dialog让用户选择是从相册中选择图片还是从摄像头中拍照。
5.选择图片和拍照操作
我们还需要实现选择图片和拍照的操作。这里使用了Ucrop的第三方库来剪裁头像图片。具体实现如下:
```
/**
* 选择图片
*/
private void pickPhoto() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, REQUEST_CODE_PICK_PHOTO);
}
/**
* 拍照
*/
private void openCamera() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQUEST_CODE_TAKE_PHOTO);
}
/**
* 获得相册图片或照片后的操作
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case REQUEST_CODE_PICK_PHOTO:
if (data != null) {
Uri originalUri = data.getData(); // 获得相册图片的uri
startCropActivity(originalUri);
}
break;
case REQUEST_CODE_TAKE_PHOTO:
if (data != null) {
Bundle bundle = data.getExtras();
if (bundle != null) {
Bitmap bitmap = (Bitmap) bundle.get("data");
if (bitmap == null) {
return;
}
Uri imageUri = Utils.saveBitmap(bitmap, Utils.getTempFile(this).getPath());
startCropActivity(imageUri);
}
}
break;
case UCrop.REQUEST_CROP:
if (data != null) {
Uri newUri = UCrop.getOutput(data);
Bitmap bitmap = Utils.decodeUri(this, newUri);
mBase64Avatar = Utils.encodeBitmap(bitmap);
ivAvatar.setImageBitmap(bitmap);
}
break;
}
}
}
/**
* 开始剪裁图片
*/
private void startCropActivity(Uri uri) {
UCrop.Options options = new UCrop.Options();
options.setToolbarTitle(getString(R.string.app_name));
options.setToolbarColor(ContextCompat.getColor(this, R.color.colorPrimary));
options.setStatusBarColor(ContextCompat.getColor(this, R.color.colorPrimaryDark));
options.setActiveWidgetColor(ContextCompat.getColor(this, R.color.colorAccent));
options.setToolbarWidgetColor(ContextCompat.getColor(this, R.color.white));
options.setCompressionQuality(80);
Uri destinationUri = Uri.fromFile(new File(getCacheDir(), String.valueOf(System.currentTimeMillis())));
UCrop.of(uri, destinationUri)
.withOptions(options)
.withAspectRatio(1, 1)
.withMaxResultSize(720, 720)
.start(this);
}
/**
* 显示选择照片、拍照的Dialog
*/
private void showPickPhotoDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("选择图片");
String[] options = {"相册选择", "拍照"};
builder.setItems(options, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
switch (i) {
case 0:
pickPhoto();
break;
case 1:
openCamera();
break;
}
}
});
builder.create().show();
}
```
这里使用了第三方库UCrop来进行图片的裁剪操作,并使用Utils.encodeBitmap、Utils.decodeUri等辅助方法对图片进行编码和解码操作。
远程服务器存储方案
对于远程服务器存储方案,我们需要使用后端框架SpringMVC来开发。具体开发方式比较复杂,需要涉及到数据库、Java Web等知识点。这里不再详细展开介绍,而推荐大家可以通过阅读SpringMVC相关的文档,自行开发实现。
总结
本文中介绍了实现Android修改个人信息的两种方案:本地存储方案和远程服务器存储方案。本地存储方案使用了SQLite数据库来实现,而远程服务器存储方案则需要使用SpringMVC后端框架进行开发。不论选择哪种方案,都是困难重重的任务,需要熟练掌握相关的技术和知识点。