简体   繁体   中英

RecyclerView Disappears When Screen Orientation is Changed

I'm working on an app that hits a web service every 10 seconds to fetch data and then populate it in a RecyclerView, if there is any data present in the JSONarray returned. Once the data is retrieved by the application, the retrieved data will be removed from the server. So that the next time the app hits the web service it may get empty arrays until the new data comes in the server.

The Problem: The RecyclerView disappears when the phone is rotated or the screen orientation is changed. This may be because, android usually destroys your application's existing Activities and recreates them when the orientation is changed. But in my case the already retrieved data will not be present in the server so the it could be showed after the activity is recreated.

I think it has to do something with saving the state by implementing the onSaveInstanceState method, but not sure on how to implement it in my code. Can anyone please tell me what changes are to be made.

MainActivity.java

public class MainActivity extends AppCompatActivity  implements SwipeRefreshLayout.OnRefreshListener{

List<DataModel> DataAdapterClassList;
RecyclerView recyclerView;
LinearLayoutManager recyclerViewlayoutManager;
RecyclerView.Adapter recyclerViewadapter;
ArrayList<String> SubjectNames;
RequestQueue requestQueue ;
SwipeRefreshLayout mSwipeRefreshLayout;
public MainActivity mainActivity;
View ChildView ;
int RecyclerViewClickedItemPOS ;
private static final String TAG = MainActivity.class.getSimpleName();
        .....//More declarations
@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    mainActivity = this;
    mRequestingLocationUpdates = false;
    mLastUpdateTime = "";
    // Update values using data stored in the Bundle.
    updateValuesFromBundle(savedInstanceState);
    mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
    mSettingsClient = LocationServices.getSettingsClient(this);
    setContentView(R.layout.activity_main);
    DataAdapterClassList = new ArrayList<>();
    SubjectNames = new ArrayList<>();
    recyclerView = (RecyclerView) findViewById(R.id.recyclerView1);
    recyclerView.setHasFixedSize(true);
    recyclerViewlayoutManager = new LinearLayoutManager(this);
    recyclerView.setLayoutManager(recyclerViewlayoutManager);
    recyclerViewlayoutManager.setReverseLayout(true);
    recyclerViewlayoutManager.setStackFromEnd(true);
            ......//location callbacks....
    startTimer();
    JSON_WEB_CALL();

}


/**Location Updates fields based on data stored in the bundle.*/
private void updateValuesFromBundle(Bundle savedInstanceState) {
    if (savedInstanceState != null) {
        if (savedInstanceState.keySet().contains(KEY_REQUESTING_LOCATION_UPDATES)) {
            mRequestingLocationUpdates = savedInstanceState.getBoolean(
                    KEY_REQUESTING_LOCATION_UPDATES);
        }
        if (savedInstanceState.keySet().contains(KEY_LOCATION)) {
            mCurrentLocation = savedInstanceState.getParcelable(KEY_LOCATION);
        }

        // Update the value of mLastUpdateTime from the Bundle and update the UI.
        if (savedInstanceState.keySet().contains(KEY_LAST_UPDATED_TIME_STRING)) {
            mLastUpdateTime = savedInstanceState.getString(KEY_LAST_UPDATED_TIME_STRING);
        }
        updateUI();
    }
}
    @Override
public void onResume() {
    super.onResume();
}

    .............//More Location Codes

@Override
public void onRefresh() {
    mSwipeRefreshLayout.setRefreshing(false);
    JSON_WEB_CALL();
}

public void JSON_WEB_CALL(){

    String HTTP_SERVER_URL= String.format("http://pastebin.com/mySampleApi/student/%1$s",mStudentRoll);
    JsonArrayRequest jsArrRequest = new JsonArrayRequest
            (Request.Method.POST, HTTP_SERVER_URL, null, new Response.Listener<JSONArray>() {

                @Override
                public void onResponse(JSONArray response) {
                    //mTxtDisplay.setText("Response: " + response.toString());

                    JSON_PARSE_DATA_AFTER_WEBCALL(response);
                    Log.i(TAG, "Hello");
                }
            }, new Response.ErrorListener() {

                @Override
                public void onErrorResponse(VolleyError error) {
                    // TODO Auto-generated method stub
                }
            }){

    };
    requestQueue = Volley.newRequestQueue(this);
    requestQueue.add(jsArrRequest);
}



public void JSON_PARSE_DATA_AFTER_WEBCALL(JSONArray array){

    for(int i = 0; i<array.length(); i++) {
        DataModel GetDataModel = new DataModel();
        JSONObject json = null;
        try {
            json = array.getJSONObject(i);
            GetDataModel.setId(json.getString("CLASS"));
            GetDataModel.setPlateNo(json.getString("HOUSE"));
            GetDataModel.setPlateCode(json.getString("IMAGEURL"));

        } catch (JSONException e) {
            e.printStackTrace();
        }
            DataAdapterClassList.add(GetDataModel);
            mSwipeRefreshLayout.setRefreshing(false);
        }
    if (array.length() != 0) {
    recyclerViewadapter = new NewRecyclerViewAdapter(DataAdapterClassList, this);
    recyclerView.setAdapter(recyclerViewadapter);
    SHOW_ALERT(array);
    sendNotification(recyclerView, array);
    }
}

@Override
public void onPause() {
    super.onPause();  
    }

@Override
public void onBackPressed() {
    moveTaskToBack(true);
}

}

NewRecyclerViewAdapter.java

public class NewRecyclerViewAdapter extends RecyclerView.Adapter<NewRecyclerViewAdapter.ViewHolder> {

Context context;
List<DataModel> dataModels;
private static int currentPosition = 0;
public Animation animationUp;
public  Animation animationDown;
public int mExpandedPosition=-1;

public NewRecyclerViewAdapter(List<DataModel> getDataAdapter, Context context){
    super();
    this.dataModels = getDataAdapter;
    this.context = context;
}


@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.new_card_view, parent, false);
    ViewHolder viewHolder = new ViewHolder(view);
    return viewHolder;
}

@Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
    DataModel dataAdapter =  dataModels.get(position)

    viewHolder.SudentClass.setText(dataAdapter.getSudentClass());
    viewHolder.SudentHouse.setText(dataAdapter.getSudentHouse());
    Glide.with(context).load(dataAdapter.getImgUrl()).into(viewHolder.imageView);
    viewHolder.linearLayout.setVisibility(View.GONE);
    final boolean isExpanded = position==mExpandedPosition;
    viewHolder.linearLayout.setVisibility(isExpanded?View.VISIBLE:View.GONE);
    viewHolder.itemView.setActivated(isExpanded);
    viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mExpandedPosition = isExpanded ? -1:position;
            //TransitionManager.beginDelayedTransition();
            notifyDataSetChanged();
        }
    });

}

@Override
public int getItemCount() {
    return dataModels.size();
}

dataAdapter.getSudentClass() ViewHolder extends RecyclerView.ViewHolder{

    public TextView StudentdataAdapter.getSudentClass();
    public TextView SudentHouse;
    public TextView StudentClass;
    public ImageView imageView;
    LinearLayout linearLayout;
    public ViewHolder(View itemView) {
        super(itemView);
        SudentHouse = (TextView) itemView.findViewById(R.id.vehicle_SudentHouse) ;
        StudentClass = (TextView) itemView.findViewById(R.id.vehicle_student_class) ;
        imageView = (ImageView) itemView.findViewById(R.id.imageView);
    }
}
}

activity_main.xml

 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/no_conn_layout"
    android:orientation="horizontal"
    android:visibility="visible">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="No Connection!!!"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Try Again" />
</LinearLayout>

<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.newcoder.student.MainActivity">

    <android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerView1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"/>

</android.support.v4.widget.SwipeRefreshLayout>

You have to handle the Configuration change in a Effective Manner

Try this code in your project

   @Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    super.onSaveInstanceState(savedInstanceState);
    mListState=recyclerView.getLayoutManager().onSaveInstanceState();
    mBundleRecyclerViewState.putParcelable(KEY_RECYCLER_STATE, mListState);
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (mBundleRecyclerViewState != null) {
        new Handler().postDelayed(new Runnable() {

            @Override
            public void run() {
                mListState = mBundleRecyclerViewState.getParcelable(KEY_RECYCLER_STATE);
                recyclerView.getLayoutManager().onRestoreInstanceState(mListState);

            }
        }, 50);

    }

    recyclerView.setLayoutManager(gridLayoutManager);
 }

Here i have used GridLayoutManager , for your purpose you can use LinearLayout .

Here is the github link for complete working project

Image Gallery Using RecyclerView

Please go through the link below -

https://developer.android.com/guide/topics/resources/runtime-changes.html#RetainingAnObject .

Idea is simple, If we set the

 // retain this fragment
 setRetainInstance(true);

inside fragment, then this fragment will not be destroyed when configuration is changed. Call your API in this fragment and get the data using getters and setters, so that you wont lose the data.

when you rotate screen that state will be saved is required used below code for.... in mainActivity

    @Override
protected void onCreate(Bundle savedInstanceState) {
    if(savedInstanceState != null) {
        DataAdapterClassList = savedInstanceState.getIntegerArrayList("key");
    }

    // Pass the imagesState to the adapter as a parameter here
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putIntegerArrayList("key", DataAdapterClassList);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM