Dre*_*rko 23 android firebase firebase-realtime-database
我正在开发一个简单的APOD应用程序,它可以实现:
RecyclerViewCardViewFirebasePicasso该应用程序从中抓取图像和文本,Firebase并将其Firebase Storage显示在a中CardView,并OnClickListener为每个设置View.当用户点击图片时,我打开一个新Activity的Intent.第二个Activity显示原始单击的图像,以及有关它的更多信息.
GridLayoutManager如果用户的手机是VERTICAL,我已经使用1列实现了这一切,如果用户的手机是HORIZONTAL则使用3列.
我遇到的问题是我似乎无法挽救RecyclerView方向改变的立场.我已经尝试了我能找到的每一个选项,但似乎都没有.唯一的结论,我可以想出,是在旋转,我毁坏Firebase的ChildEventListener,以避免内存泄漏,一旦定位完成后,Firebase再查询,因为新实例的数据库ChildEventListener.
有什么方法可以挽救我RecyclerView对方向改变的立场吗?我不想要,android:configChanges因为它不会让我改变我的布局,我已经尝试过保存为一个Parcelable,这是不成功的.我确信这很容易让我失踪,但是,嘿,我是新手.我非常感谢您对我的代码的任何帮助或建议.谢谢!
下面是我的课程,我只简化了必要的代码.
主要活动
public class MainActivity extends AppCompatActivity {
private RecyclerAdapter mRecyclerAdapter;
private DatabaseReference mDatabaseReference;
private RecyclerView mRecyclerView;
private Query query;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
setContentView(R.layout.activity_main);
getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final int columns = getResources().getInteger(R.integer.gallery_columns);
mDatabaseReference = FirebaseDatabase.getInstance().getReference();
query = mDatabaseReference.child("apod").orderByChild("date");
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new GridLayoutManager(this, columns));
mRecyclerAdapter = new RecyclerAdapter(this, query);
mRecyclerView.setAdapter(mRecyclerAdapter);
}
@Override
public void onDestroy() {
mRecyclerAdapter.cleanupListener();
}
}
Run Code Online (Sandbox Code Playgroud)
RecyclerAdapter
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ApodViewHolder> {
private final Context mContext;
private final ChildEventListener mChildEventListener;
private final Query mDatabaseReference;
private final List<String> apodListIds = new ArrayList<>();
private final List<Apod> apodList = new ArrayList<>();
public RecyclerAdapter(final Context context, Query ref) {
mContext = context;
mDatabaseReference = ref;
ChildEventListener childEventListener = new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
int oldListSize = getItemCount();
Apod apod = dataSnapshot.getValue(Apod.class);
//Add data and IDs to the list
apodListIds.add(dataSnapshot.getKey());
apodList.add(apod);
//Update the RecyclerView
notifyItemInserted(oldListSize - getItemCount() - 1);
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
String apodKey = dataSnapshot.getKey();
int apodIndex = apodListIds.indexOf(apodKey);
if (apodIndex > -1) {
// Remove data and IDs from the list
apodListIds.remove(apodIndex);
apodList.remove(apodIndex);
// Update the RecyclerView
notifyDataSetChanged();
}
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
};
ref.addChildEventListener(childEventListener);
mChildEventListener = childEventListener;
}
@Override
public int getItemCount() {
return apodList.size();
}
public void cleanupListener() {
if (mChildEventListener != null) {
mDatabaseReference.removeEventListener(mChildEventListener);
}
}
}
Run Code Online (Sandbox Code Playgroud)
旋转活动被破坏并再次重新创建,这意味着所有对象都被销毁并重新创建,并且布局也会重新绘制.
你想停止重新创建你可以使用android:configChanges的活动,但这是不好的做法,也不是正确的方法.
现在唯一剩下的就是在轮换之前保存recyclerview的位置,并在重新创建活动之后获取它.
//保存recyclerview的位置
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putInt("position", mRecyclerView.getAdapterPosition()); // get current recycle view position here.
super.onSaveInstanceState(savedInstanceState);
}
Run Code Online (Sandbox Code Playgroud)
//恢复价值
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
setContentView(R.layout.activity_main);
getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final int columns = getResources().getInteger(R.integer.gallery_columns);
mDatabaseReference = FirebaseDatabase.getInstance().getReference();
query = mDatabaseReference.child("apod").orderByChild("date");
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new GridLayoutManager(this, columns));
mRecyclerAdapter = new RecyclerAdapter(this, query);
mRecyclerView.setAdapter(mRecyclerAdapter);
if(savedInstanceState != null){
// scroll to existing position which exist before rotation.
mRecyclerView.scrollToPosition(savedInstanceState.getInt("position"));
}
}
Run Code Online (Sandbox Code Playgroud)
希望这些能帮到你.
编辑:
我终于能够使用多种因素来完成这项工作。如果其中任何一项被遗漏,它就根本行不通。
GridLayoutManager在我的 onCreate 中新建
gridLayoutManager = new GridLayoutManager(getApplicationContext(), columns);
Run Code Online (Sandbox Code Playgroud)
在 onPause 中保存 RecyclerView 状态
private final String KEY_RECYCLER_STATE = "recycler_state";
private static Bundle mBundleRecyclerViewState;
private Parcelable mListState = null;`
@Override
protected void onPause() {
super.onPause();
mBundleRecyclerViewState = new Bundle();
mListState = mRecyclerView.getLayoutManager().onSaveInstanceState();
mBundleRecyclerViewState.putParcelable(KEY_RECYCLER_STATE, mListState);
}
Run Code Online (Sandbox Code Playgroud)
包括configChanges在AndroidManifest.xml
保存和恢复RecyclerView状态是不够的。我也不得不违背AndroidManifest.xml常规并将我的更改为 'android:configChanges="orientation|screenSize"'
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize"
>
Run Code Online (Sandbox Code Playgroud)
恢复RecyclerView状态onConfigurationChanged使用Handler
处理程序是最重要的部分之一,如果不包含它,它将无法工作,并且RecyclerView将重置为 0的位置。我想这是几年前的一个缺陷,并且从未修复过。然后我根据方向更改了GridLayoutManager's setSpanCount。
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
columns = getResources().getInteger(R.integer.gallery_columns);
if (mBundleRecyclerViewState != null) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mListState = mBundleRecyclerViewState.getParcelable(KEY_RECYCLER_STATE);
mRecyclerView.getLayoutManager().onRestoreInstanceState(mListState);
}
}, 50);
}
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
gridLayoutManager.setSpanCount(columns);
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
gridLayoutManager.setSpanCount(columns);
}
mRecyclerView.setLayoutManager(gridLayoutManager);
}
Run Code Online (Sandbox Code Playgroud)
就像我说的,所有这些变化都需要包括在内,至少对我来说是这样。我不知道这是否是最有效的方法,但在花了很多小时后,它对我有用。
| 归档时间: |
|
| 查看次数: |
9763 次 |
| 最近记录: |