兄弟们,不知道你们有没有被Android的多页面开发虐过?就是那种点击注册按钮后APP直接闪退,或者选完头像发现照片没显示的绝望...(别问我怎么知道的😭)今天咱们就来把“多个Activity使用”这个知识点按在地上摩擦,全程无尿点,代码复制就能跑起来!
一、为什么你的注册页像个“自闭症患者”?
先灵魂拷问:你是不是把登录框、头像选择、提交按钮全堆在一个Activity里了?这种“全家桶式”写法会导致:
- 代码臃肿度堪比春运火车 - 一个Java文件动辄800+行,改行密码校验逻辑得像考古一样小心翼翼
- 内存泄漏风险直逼渣男承诺 - 图片加载不及时释放,用户多切换几次头像,APP就直接卡成PPT
- 用户体验仿佛在玩迷宫 - 没有清晰的页面流转,用户可能永远找不到从哪里换头像
解决方案?多Activity架构!让登录页、头像选择页各司其职,就像让专业的人干专业的事——总不能让你家厨师同时兼职务农种菜吧?
二、准备打仗:你的装备清单
在写代码前,请确认项目里已经配齐这些“武器”:
// build.gradle 必备依赖
android {
compileSdk 33
defaultConfig {
minSdk 21
targetSdk 33
}
}
// 处理权限申请的“尚方宝剑”
implementation 'com.guolindev.permissionx:permissionx:1.7.1'
// 图片加载的“瑞士军刀”
implementation 'com.github.bumptech.glide:glide:4.15.1'
权限声明别忘了在AndroidManifest.xml里“上户口”:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
三、实战开始:三步打造撩妹级注册页
第1步:建造注册页“毛坯房”(MainActivity)
先搞定布局文件activity_main.xml:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp"
android:orientation="vertical">
<!-- 头像选择区 -->
<ImageView
android:id="@+id/ivAvatar"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center_horizontal"
android:src="@drawable/default_avatar" <!-- 准备张默认头像图片 -->
android:onClick="chooseAvatar" />
<!-- 输入框组 -->
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.Material3.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/etUsername"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="取个闪亮的用户名"/>
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/btnSubmit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="立即注册"
android:onClick="submitForm" />
</LinearLayout>
接着是MainActivity.java的核心代码:
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CODE_AVATAR = 100;
private ImageView ivAvatar;
private EditText etUsername;
private Uri avatarUri; // 记录选中的头像路径
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivAvatar = findViewById(R.id.ivAvatar);
etUsername = findViewById(R.id.etUsername);
}
// 处理头像选择按钮点击
public void chooseAvatar(View view) {
Intent intent = new Intent(this, AvatarSelectActivity.class);
startActivityForResult(intent, REQUEST_CODE_AVATAR);
}
// 接收回调数据的“快递驿站”
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_AVATAR && resultCode == RESULT_OK) {
if (data != null) {
avatarUri = data.getParcelableExtra("avatar");
Glide.with(this).load(avatarUri).into(ivAvatar);
}
}
}
// 提交表单时的“安检程序”
public void submitForm(View view) {
if (avatarUri == null) {
Toast.makeText(this, "请先选择帅气的头像", Toast.LENGTH_SHORT).show();
return;
}
if (etUsername.getText().toString().trim().isEmpty()) {
etUsername.setError("填个用户名呗");
return;
}
// 这里接后续注册逻辑
Toast.makeText(this, "注册成功!", Toast.LENGTH_SHORT).show();
}
}
第2步:打造头像选择“精品店”(AvatarSelectActivity)
先创建activity_avatar_select.xml:
<GridView
android:id="@+id/gvAvatars"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="3"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:padding="10dp" />
对应的AvatarSelectActivity.java:
public class AvatarSelectActivity extends AppCompatActivity {
private GridView gvAvatars;
private final int[] avatarRes = {R.drawable.avatar1, R.drawable.avatar2,
R.drawable.avatar3, R.drawable.avatar4}; // 预置头像资源
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_avatar_select);
gvAvatars = findViewById(R.id.gvAvatars);
gvAvatars.setAdapter(new AvatarAdapter());
gvAvatars.setOnItemClickListener((parent, view, position, id) -> {
Intent resultIntent = new Intent();
resultIntent.putExtra("avatar", Uri.parse("android.resource://" + getPackageName() + "/" + avatarRes[position]));
setResult(RESULT_OK, resultIntent);
finish(); // 选完立即关闭页面
});
}
// 自定义适配器
class AvatarAdapter extends BaseAdapter {
@Override
public int getCount() { return avatarRes.length; }
@Override
public Object getItem(int position) { return avatarRes[position]; }
@Override
public long getItemId(int position) { return position; }
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = convertView != null ? (ImageView) convertView : new ImageView(AvatarSelectActivity.this);
imageView.setImageResource(avatarRes[position]);
imageView.setLayoutParams(new GridView.LayoutParams(200, 200));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
return imageView;
}
}
}
第3步:处理相册选择的“高能预警”
如果想允许从相册选择,需要在AvatarSelectActivity里添加:
// 在点击事件中增加选项弹窗
private void showImageSourceDialog() {
new AlertDialog.Builder(this)
.setItems(new String[]{"系统头像", "从相册选择"}, (dialog, which) -> {
if (which == 0) {
// 使用系统头像
} else {
// 检查权限
PermissionX.init(this)
.permissions(Manifest.permission.READ_EXTERNAL_STORAGE)
.request((allGranted, grantedList, deniedList) -> {
if (allGranted) openGallery();
else Toast.makeText(this, "需要存储权限才能选照片", Toast.LENGTH_SHORT).show();
});
}
}).show();
}
// 打开相册
private void openGallery() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, REQUEST_CODE_GALLERY);
}
四、躲坑指南:血泪换来的经验
- 内存泄漏预防:在MainActivity的onDestroy里调用Glide.with(this).clear(ivAvatar)
- 大图片处理:相册选择时添加图片压缩,避免加载原图导致OOM
- 生命周期管理:在onSaveInstanceState里保存avatarUri,屏幕旋转时不丢失数据
- 键盘隐藏彩蛋:在EditText失去焦点时自动隐藏键盘:
etUsername.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
});
五、完整代码彩蛋
由于篇幅限制,完整代码已打包在Github仓库(虚构示例,实际需自行实现):
# 假想的仓库地址
git clone https://github.com/example/avatar-registration-demo
关键文件清单:
- MainActivity.java - 注册主页面
- AvatarSelectActivity.java - 头像选择页
- activity_main.xml / activity_avatar_select.xml - 页面布局
- AvatarAdapter.java - 头像适配器
六、总结
多Activity开发就像组乐队——每个Activity都是独立乐手,通过Intent这个“指挥棒”协同合作。记住这几个关键点:
- startActivityForResult是页面间传值的“电话热线”
- onActivityResult是接收回复的“客服专员”
- setResult是回传数据的“快递小哥”
- Glide是图片处理的“美图秀秀”
现在你已经掌握了打造不闪退、体验顺滑的多页面注册功能的秘籍!下次产品经理再提“要能换头像”时,你就可以优雅地抛出这个实现方案了。如果还有问题,欢迎在评论区交流——毕竟,程序员何苦为难程序员呢?
4610

被折叠的 条评论
为什么被折叠?



