RxPaparazzo là một thư viện mở nguồn dành cho nền tảng Android, được thiết kế để đơn giản hóa quy trình xử lý hình ảnh thông qua mô hình lập trình phản ứng (reactive programming) dựa trên RxJava. Thay vì viết hàng chục dòng mã để quản lý intent, xử lý quyền, khởi tạo activity chọn ảnh hoặc cắt ảnh, thư viện này đóng gói toàn bộ luồng công việc thành các chuỗi Observable có thể kết hợp, bắt lỗi và hủy bỏ linh hoạt.
Cơ chế hoạt động cốt lõi
Thư viện vận hành dựa trên ba thành phần chính:
- RxJava 2.x: Làm nền tảng cho việc biểu diễn các thao tác bất đồng bộ (chụp ảnh, tải file, cắt ảnh) dưới dạng luồng dữ liệu có thể quan sát.
- RxPermissions: Tự động yêu cầu và theo dõi trạng thái quyền truy cập máy ảnh hoặc lưu trữ — không cần viết
onRequestPermissionsResultthủ công. - UCrop: Cung cấp giao diện cắt ảnh chuẩn Material với tùy chỉnh tỷ lệ, khung giới hạn và định dạng đầu ra.
Tích hợp nhanh
Thêm kho lưu trữ JitPack và dependency vào build.gradle cấp module:
repositories {
maven { url 'https://jitpack.io' }
}
dependencies {
implementation 'com.github.miguelbcr:RxPaparazzo:0.6.1-2.x'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'io.reactivex.rxjava2:rxjava:2.2.21'
}
Khai báo FileProvider trong AndroidManifest.xml:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
Và tạo tệp res/xml/file_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="external_files_path" path="." />
</paths>
Mẫu triển khai cụ thể
Chụp ảnh trực tiếp từ camera:
RxPaparazzo.single(this)
.size(1024, 768) // giới hạn kích thước ảnh đầu ra
.usingCamera()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
result -> {
if (result.isOk()) {
ImageView imageView = findViewById(R.id.preview);
Glide.with(this).load(result.file()).into(imageView);
} else {
Toast.makeText(this, "Người dùng hủy thao tác", Toast.LENGTH_SHORT).show();
}
},
error -> Log.e("RxPaparazzo", "Lỗi khi chụp ảnh", error)
);
Chọn ảnh từ thư viện và cắt tự động:
RxPaparazzo.single(this)
.crop()
.aspectRatio(1f, 1f) // cắt vuông
.maxResultSize(800, 800) // giới hạn ảnh sau cắt
.usingGallery()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
result -> {
File croppedImage = result.file();
// Xử lý ảnh đã cắt: upload, lưu local, hiển thị...
},
Throwable::printStackTrace
);
Kết hợp nhiều bước (chọn → cắt → nén):
RxPaparazzo.single(this)
.usingGallery()
.crop()
.compress(85) // chất lượng JPEG %
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
result -> updateProfileAvatar(result.file()),
error -> handleError(error)
);