10个实战项目吃透Android开发:Android_Blog_Demos全解析

10个实战项目吃透Android开发:Android_Blog_Demos全解析

【免费下载链接】Android_Blog_Demos source code in blog~ 【免费下载链接】Android_Blog_Demos 项目地址: https://gitcode.com/gh_mirrors/an/Android_Blog_Demos

你是否还在为Android开发中的巨图加载、性能优化、自定义View等难题发愁?是否渴望通过实战项目快速提升技能?本文将全面解析Android_Blog_Demos项目,带你掌握10个核心技术场景的实现方案,从根本上解决开发痛点。

读完本文你将获得:

  • 高清巨图加载的完整解决方案,拒绝OOM(内存溢出)
  • UI性能优化的实战技巧,提升应用流畅度
  • MVP架构在Android中的最佳实践
  • 自定义View的核心原理与实现方法
  • 多线程编程的高效处理方式

项目概述

Android_Blog_Demos是一个专注于Android开发实战的开源项目,存储了多个实用技术场景的完整实现代码。该项目由资深Android开发者维护,持续更新中,是学习Android开发的优质资源。

项目结构

项目采用模块化结构设计,主要包含以下核心模块:

模块名称功能描述技术要点
largeImage高清巨图加载方案图片分片加载、手势缩放
performance_01UI性能优化OverDraw优化、布局优化
mvpMVP架构实现架构设计、接口封装
vdhViewDragHelper实战自定义ViewGroup、手势处理
toolbarToolBar与Theme应用5.x新特性、样式定制
nav自定义NavigationView侧边栏导航、菜单设计
colour_app_01不规则图像填充图像着色、Canvas绘制
intentservice后台任务处理IntentService、HandlerThread
jniJNI交互示例原生开发、Java与C交互
dl插件化开发动态加载、组件化

环境要求

  • Android Studio 3.0+
  • Gradle 4.1+
  • Android SDK 21+
  • JDK 8+

快速开始

项目导入

  1. 克隆仓库到本地:
git clone https://gitcode.com/gh_mirrors/an/Android_Blog_Demos.git
  1. 在Android Studio中直接以项目导入:

    • 打开Android Studio
    • 选择"Open an existing Android Studio project"
    • 导航到克隆的项目目录并选择
    • 等待Gradle同步完成
  2. 更新项目:

cd Android_Blog_Demos
git pull

核心技术场景解析

1. 高清加载巨图方案

痛点分析

传统的ImageView加载大图时容易出现OOM异常,尤其是当图片分辨率远大于设备屏幕分辨率时。Android_Blog_Demos提供了一种高效的巨图加载方案,无需压缩图片即可实现高清显示。

实现原理

该方案的核心是通过自定义LargeImageView控件,实现图片的分片加载和显示:

public class LargeImageView extends View {
    private BitmapRegionDecoder mDecoder;
    private Rect mRect = new Rect();
    private MoveGestureDetector mDetector;
    private Matrix mMatrix = new Matrix();
    private float mScale = 1.0f;
    private PointF mLastMove = new PointF();
    
    // 初始化图片解码器
    public void setImage(InputStream is) {
        try {
            mDecoder = BitmapRegionDecoder.newInstance(is, false);
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(is, null, options);
            requestLayout();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    // 绘制指定区域的图片
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mDecoder == null) return;
        
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        Bitmap bitmap = mDecoder.decodeRegion(mRect, options);
        
        Matrix matrix = new Matrix();
        matrix.setScale(mScale, mScale);
        canvas.drawBitmap(bitmap, matrix, null);
        bitmap.recycle();
    }
    
    // 处理手势缩放和移动
    private class MoveGestureListener extends SimpleOnMoveGestureListener {
        @Override
        public boolean onMove(MoveGestureDetector detector) {
            // 处理移动逻辑
            invalidate();
            return true;
        }
    }
}
使用方法

在布局文件中添加自定义LargeImageView:

<com.zhy.blogcodes.largeImage.view.LargeImageView
    android:id="@+id/id_largeImage"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

在Activity中加载图片:

public class LargeImageViewActivity extends AppCompatActivity {
    private LargeImageView mImageView;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_large_image_view);
        
        mImageView = (LargeImageView) findViewById(R.id.id_largeImage);
        
        try {
            InputStream is = getAssets().open("tangyan.jpg");
            mImageView.setImage(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
流程图解

mermaid

2. UI性能优化实战

痛点分析

Android应用的UI性能直接影响用户体验,常见的性能问题包括卡顿、掉帧等。Android_Blog_Demos提供了一套完整的UI性能优化方案,帮助开发者识别和解决绘制中的性能问题。

实现方案
  1. OverDraw优化

OverDraw(过度绘制)是指在屏幕上的同一个像素点被绘制了多次,这会浪费GPU资源并导致性能下降。项目中的OverDrawActivity01和OverDrawActivity02展示了如何检测和解决过度绘制问题:

public class OverDrawActivity01 extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 开启GPU过度绘制调试
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
                WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
        
        // 第一种布局: 存在严重的OverDraw
        setContentView(R.layout.activity_overdraw_01);
        
        // 优化方案:
        // 1. 移除不必要的背景
        // 2. 使用merge标签减少布局层级
        // 3. 合理使用clipRect()和quickReject()
    }
}
  1. 布局优化

CompareLayoutActivity展示了不同布局实现方式对性能的影响:

public class CompareLayoutActivity extends ActionBarActivity {
    private static final String TAG = "CompareLayoutActivity";
    private LinearLayout mLinearLayout;
    private RelativeLayout mRelativeLayout;
    private FrameLayout mFrameLayout;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_compare_layouts);
        
        mLinearLayout = (LinearLayout) findViewById(R.id.ll_test);
        mRelativeLayout = (RelativeLayout) findViewById(R.id.rl_test);
        mFrameLayout = (FrameLayout) findViewById(R.id.fl_test);
        
        // 测量不同布局的绘制时间
        measureLayoutPerformance();
    }
    
    private void measureLayoutPerformance() {
        // 测量LinearLayout性能
        long start = System.nanoTime();
        mLinearLayout.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        long end = System.nanoTime();
        Log.d(TAG, "LinearLayout measure time: " + (end - start) + "ns");
        
        // 类似方式测量其他布局...
    }
}
性能对比
布局类型测量时间(ns)绘制性能适用场景
LinearLayout12000简单线性排列
RelativeLayout28000复杂相对位置
FrameLayout8000最高层叠布局
ConstraintLayout15000复杂布局

3. MVP架构实现

痛点分析

传统的Android开发中,Activity/Fragment往往承担了过多责任,导致代码臃肿、难以维护和测试。MVP(Model-View-Presenter)架构通过分离关注点,使代码结构更清晰,提高可维护性和可测试性。

架构设计

项目中的mvp模块完整实现了MVP架构,其核心组成如下:

  1. Model层:处理数据逻辑
  2. View层:负责UI展示
  3. Presenter层:协调Model和View,处理业务逻辑

mermaid

核心实现
  1. Model层实现:
public interface IUserBiz {
    void login(String username, String password, OnLoginListener listener);
}

public class UserBiz implements IUserBiz {
    @Override
    public void login(final String username, final String password, final OnLoginListener listener) {
        // 模拟子线程执行耗时操作
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                // 模拟登录成功
                if ("zhy".equals(username) && "123".equals(password)) {
                    User user = new User();
                    user.setUsername(username);
                    user.setPassword(password);
                    listener.loginSuccess(user);
                } else {
                    listener.loginFailed();
                }
            }
        }.start();
    }
}
  1. View层接口:
public interface IUserLoginView {
    String getUsername();
    String getPassword();
    void clearUsername();
    void clearPassword();
    void showLoading();
    void hideLoading();
    void toMainActivity(User user);
    void showFailedError();
}
  1. Presenter层实现:
public class UserLoginPresenter {
    private IUserBiz userBiz;
    private IUserLoginView userLoginView;
    private Handler mHandler = new Handler();
    
    public UserLoginPresenter(IUserLoginView view) {
        this.userLoginView = view;
        this.userBiz = new UserBiz();
    }
    
    public void login() {
        userLoginView.showLoading();
        userBiz.login(userLoginView.getUsername(), userLoginView.getPassword(), 
            new OnLoginListener() {
                @Override
                public void loginSuccess(final User user) {
                    // 在UI线程执行
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            userLoginView.toMainActivity(user);
                            userLoginView.hideLoading();
                        }
                    });
                }
                
                @Override
                public void loginFailed() {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            userLoginView.showFailedError();
                            userLoginView.hideLoading();
                        }
                    });
                }
            });
    }
    
    public void clear() {
        userLoginView.clearUsername();
        userLoginView.clearPassword();
    }
    
    public void onDestroy() {
        userLoginView = null;
    }
}
  1. View层实现:
public class UserLoginActivity extends ActionBarActivity implements IUserLoginView {
    private EditText mEtUsername, mEtPassword;
    private Button mBtnLogin, mBtnClear;
    private ProgressBar mPbLoading;
    private UserLoginPresenter mUserLoginPresenter;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_user_login);
        
        initViews();
        mUserLoginPresenter = new UserLoginPresenter(this);
    }
    
    private void initViews() {
        mEtUsername = (EditText) findViewById(R.id.id_et_username);
        mEtPassword = (EditText) findViewById(R.id.id_et_password);
        mBtnLogin = (Button) findViewById(R.id.id_btn_login);
        mBtnClear = (Button) findViewById(R.id.id_btn_clear);
        mPbLoading = (ProgressBar) findViewById(R.id.id_pb_loading);
        
        mBtnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mUserLoginPresenter.login();
            }
        });
        
        mBtnClear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mUserLoginPresenter.clear();
            }
        });
    }
    
    // 实现IUserLoginView接口方法...
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mUserLoginPresenter.onDestroy();
    }
}

其他实用技术场景

4. ViewDragHelper实战

ViewDragHelper是Android支持库中的一个强大工具,简化了自定义ViewGroup中的手势处理。项目中的vdh模块展示了如何使用ViewDragHelper实现类似DrawerLayout的侧边栏效果:

public class LeftDrawerLayout extends ViewGroup {
    private ViewDragHelper mDragHelper;
    private View mMainContent;
    private View mLeftMenu;
    private int mMenuWidth;
    
    public LeftDrawerLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        mDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
            @Override
            public boolean tryCaptureView(View child, int pointerId) {
                // 只允许拖动主内容视图
                return child == mMainContent;
            }
            
            @Override
            public int clampViewPositionHorizontal(View child, int left, int dx) {
                // 限制水平拖动范围
                return Math.max(0, Math.min(left, mMenuWidth));
            }
            
            @Override
            public void onViewReleased(View releasedChild, float xvel, float yvel) {
                // 处理释放时的动画
                int finalLeft = (xvel > 0 || (xvel == 0 && releasedChild.getLeft() > mMenuWidth / 2)) ? 
                    mMenuWidth : 0;
                mDragHelper.settleCapturedViewAt(finalLeft, releasedChild.getTop());
                invalidate();
            }
            
            @Override
            public int getViewHorizontalDragRange(View child) {
                return mMenuWidth;
            }
        });
    }
    
    // 其他必要实现...
    
    @Override
    public void computeScroll() {
        if (mDragHelper.continueSettling(true)) {
            ViewCompat.postInvalidateOnAnimation(this);
        }
    }
}

5. 多线程编程

项目中的intentservice模块展示了如何使用IntentService和HandlerThread处理后台任务:

  1. IntentService实现:
public class UploadImgService extends IntentService {
    private static final String TAG = "UploadImgService";
    
    public static final String ACTION_UPLOAD_IMG = "com.zhy.blogcodes.intentservice.action.UPLOAD_IMAGE";
    public static final String EXTRA_IMG_PATH = "com.zhy.blogcodes.intentservice.extra.IMG_PATH";
    
    public UploadImgService() {
        super("UploadImgService");
    }
    
    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent != null) {
            final String action = intent.getAction();
            if (ACTION_UPLOAD_IMG.equals(action)) {
                final String path = intent.getStringExtra(EXTRA_IMG_PATH);
                handleUploadImg(path);
            }
        }
    }
    
    private void handleUploadImg(String path) {
        // 模拟上传耗时
        try {
            Thread.sleep(3000);
            Log.d(TAG, "上传图片成功: " + path);
            
            // 发送广播通知上传结果
            Intent broadcastIntent = new Intent(IntentServiceActivity.ACTION_UPLOAD_RESULT);
            broadcastIntent.putExtra(IntentServiceActivity.EXTRA_RESULT, "上传成功");
            LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
  1. HandlerThread使用:
public class HandlerThreadActivity extends AppCompatActivity {
    private static final String TAG = "HandlerThreadActivity";
    private Handler mUIHandler = new Handler();
    private Handler mWorkHandler;
    private HandlerThread mHandlerThread;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_thread_handler);
        
        // 创建HandlerThread
        mHandlerThread = new HandlerThread("WorkHandlerThread");
        mHandlerThread.start();
        
        // 在HandlerThread的Looper上创建Handler
        mWorkHandler = new Handler(mHandlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                // 后台线程处理任务
                Log.d(TAG, "工作线程: " + Thread.currentThread().getName());
                
                // 模拟耗时操作
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                // 发送结果到UI线程
                mUIHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        // 更新UI
                        Toast.makeText(HandlerThreadActivity.this, "任务完成", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        };
        
        // 点击按钮开始任务
        findViewById(R.id.id_btn_start).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mWorkHandler.sendEmptyMessage(1);
            }
        });
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 释放资源
        mHandlerThread.quit();
    }
}

项目价值与应用场景

Android_Blog_Demos项目不仅提供了多个实用技术场景的实现,更为开发者提供了以下价值:

  1. 学习价值:通过阅读和分析源代码,深入理解Android核心技术的实现原理。

  2. 参考价值:项目中的每个模块都是一个独立的技术解决方案,可直接应用到实际项目中。

  3. 扩展价值:基于现有实现,可以快速扩展出更复杂的功能。

适用人群

  • Android初学者:通过实战项目快速入门
  • 中级开发者:提升技术深度,解决实际问题
  • 高级开发者:参考架构设计,优化现有项目

总结与展望

Android_Blog_Demos项目涵盖了Android开发中的多个核心技术场景,从UI优化到架构设计,从基础控件到高级特性,为开发者提供了宝贵的实战经验。通过深入学习和实践这些技术,能够显著提升Android开发技能和项目质量。

未来,该项目可能会继续扩展以下方向:

  • Kotlin语言重构
  • Jetpack组件的应用
  • 响应式编程(RxJava/Kotlin Flow)
  • 模块化和组件化架构

希望本文的解析能够帮助你更好地理解和使用Android_Blog_Demos项目,在Android开发的道路上不断进步。如果你觉得本文有价值,请点赞、收藏并关注,后续将带来更多Android实战技术解析。

参考资料

  • Android官方开发文档
  • Android性能优化典范
  • 《Android开发艺术探索》
  • 《Android进阶之光》

【免费下载链接】Android_Blog_Demos source code in blog~ 【免费下载链接】Android_Blog_Demos 项目地址: https://gitcode.com/gh_mirrors/an/Android_Blog_Demos

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

抵扣说明:

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

余额充值