Android语言基础教程(90)Android多个Activity的使用范例之带选择头像的用户注册页面:笑死!Android多Activity翻车现场?手把手教你做个能换头像的注册页,代码拿去就能用

兄弟们,不知道你们有没有被Android的多页面开发虐过?就是那种点击注册按钮后APP直接闪退,或者选完头像发现照片没显示的绝望...(别问我怎么知道的😭)今天咱们就来把“多个Activity使用”这个知识点按在地上摩擦,全程无尿点,代码复制就能跑起来!

一、为什么你的注册页像个“自闭症患者”?

先灵魂拷问:你是不是把登录框、头像选择、提交按钮全堆在一个Activity里了?这种“全家桶式”写法会导致:

  1. 代码臃肿度堪比春运火车 - 一个Java文件动辄800+行,改行密码校验逻辑得像考古一样小心翼翼
  2. 内存泄漏风险直逼渣男承诺 - 图片加载不及时释放,用户多切换几次头像,APP就直接卡成PPT
  3. 用户体验仿佛在玩迷宫 - 没有清晰的页面流转,用户可能永远找不到从哪里换头像

解决方案?多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);
}

四、躲坑指南:血泪换来的经验

  1. 内存泄漏预防:在MainActivity的onDestroy里调用Glide.with(this).clear(ivAvatar)
  2. 大图片处理:相册选择时添加图片压缩,避免加载原图导致OOM
  3. 生命周期管理:在onSaveInstanceState里保存avatarUri,屏幕旋转时不丢失数据
  4. 键盘隐藏彩蛋:在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这个“指挥棒”协同合作。记住这几个关键点:

  1. startActivityForResult是页面间传值的“电话热线”
  2. onActivityResult是接收回复的“客服专员”
  3. setResult是回传数据的“快递小哥”
  4. Glide是图片处理的“美图秀秀”

现在你已经掌握了打造不闪退、体验顺滑的多页面注册功能的秘籍!下次产品经理再提“要能换头像”时,你就可以优雅地抛出这个实现方案了。如果还有问题,欢迎在评论区交流——毕竟,程序员何苦为难程序员呢?

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

值引力

持续创作,多谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值