Android Studio开发PDF阅读器如何实现退出后记忆上次阅读页码,集成barteksc/AndroidPdfViewer
实现PDF阅读进度持久化方案
你当前使用的onSaveInstanceState仅能处理页面临时销毁(如屏幕旋转、系统后台回收)的场景,退出Activity后存储的页码会被清空。要实现退出阅读页后重新进入仍能定位到上次阅读位置,需要使用SharedPreferences做持久化存储,且以书籍ID为存储key区分不同书籍的阅读进度,具体修改如下:
修改步骤
- 加载PDF前读取对应书籍的已存储进度
在loadBookFromUrl方法中,调用fromBytes加载PDF之前,先从SharedPreferences读取该bookId对应的阅读进度,默认值为0(即第一页) - 页码变化时实时存储进度
在OnPageChangeListener的onPageChanged回调中,每次页码切换后将最新页码写入SharedPreferences
完整修改后代码
public class PdfViewActivity extends AppCompatActivity { private ActivityPdfViewBinding binding; private String bookId; private static final String TAG = "PDF_VIEW_TAG"; private int mCurrentPage = 0; // 定义SharedPreferences相关常量 private static final String SP_NAME = "PdfReadProgress"; private static final String SP_KEY_PREFIX = "progress_"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityPdfViewBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); Intent intent = getIntent(); bookId = intent.getStringExtra("bookId"); Log.d(TAG, "onCreate: BookId :"+bookId); loadBookDetails(); binding.backBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { onBackPressed(); } }); } private void loadBookDetails() { Log.d(TAG, "loadBookDetails: Get PDF Url from database"); //Step 1 : Get bookUrl using bookId DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Books"); ref.child(bookId) .addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { //get bookUrl String pdfUrl = ""+snapshot.child("url").getValue(); Log.d(TAG, "onDataChange: PDF Url: "+pdfUrl); //Step 2 : Load pdf using that url from Firebase storage loadBookFromUrl(pdfUrl); } @Override public void onCancelled(@NonNull DatabaseError error) { } }); } private void loadBookFromUrl(String pdfUrl) { Log.d(TAG, "loadBookFromUrl: Get PDF from storage"); StorageReference reference = FirebaseStorage.getInstance().getReferenceFromUrl(pdfUrl); reference.getBytes(Constants.MAX_BYTES_PDF) .addOnSuccessListener(new OnSuccessListener<byte[]>() { @Override public void onSuccess(byte[] bytes) { // 读取已保存的阅读进度 SharedPreferences sp = getSharedPreferences(SP_NAME, MODE_PRIVATE); mCurrentPage = sp.getInt(SP_KEY_PREFIX + bookId, 0); //load pdf book using bytes binding.pdfView.fromBytes(bytes) .swipeHorizontal(false) // 设置false为竖直滚动 .defaultPage(mCurrentPage) .onPageChange(new OnPageChangeListener() { @Override public void onPageChanged(int page, int pageCount) { // 工具栏显示当前页码和总页码 int currentpage = page + 1; binding.toolbarSubtitleTv.setText(currentpage+"/"+pageCount); Log.d(TAG, "onPageChanged: "+currentpage+"/"+pageCount); // 保存最新阅读进度 sp.edit().putInt(SP_KEY_PREFIX + bookId, page).apply(); } }) .onError(new OnErrorListener() { @Override public void onError(Throwable t) { Log.d(TAG, "onError: "+t.getMessage()); Toast.makeText(PdfViewActivity.this, ""+t.getMessage(), Toast.LENGTH_SHORT).show(); } }) .onPageError(new OnPageErrorListener() { @Override public void onPageError(int page, Throwable t) { Log.d(TAG, "onPageError: "+t.getMessage()); Toast.makeText(PdfViewActivity.this, ""+t.getMessage(), Toast.LENGTH_SHORT).show(); } }) .load(); binding.progressBar.setVisibility(View.GONE); } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { Log.d(TAG, "onFailure: "+e.getMessage()); binding.progressBar.setVisibility(View.GONE); } }); } }
补充说明
如果你的应用支持多账号登录,可在存储进度的key中拼接用户ID,避免不同账号的同本书籍进度冲突。原有用于临时状态保存的onSaveInstanceState和onRestoreInstanceState方法可直接删除,也可保留用于处理屏幕旋转等临时销毁场景,逻辑不冲突。
内容的提问来源于stack exchange,提问作者Phạm Hải Đăng - 18A02
相关产品推荐
相关产品推荐

