【问题标题】:ListView not being destroyed/deflated on orientation changeListView 在方向改变时没有被破坏/放气
【发布时间】:2013-11-08 23:59:56
【问题描述】:

我遇到了这个问题,当我更改设备的方向时,由于某种原因,与我的 ListFragment 关联的 ListView 的屏幕表示被保留,并且新的 ListView 在其下方膨胀。为了给你一些背景信息,我正在创建一个非常简单的应用程序,其目的是测试我创建的一些 DAO 对象。我更愿意发布一些截图来描述我的应用程序正在经历的行为,但不幸的是,我目前的声誉太低了。

我能描述的最好的方法是,当我将设备的方向从纵向更改为横向(反之亦然)时,它会膨胀一个全新的 ListView 而不会缩小前一个。我已经研究了几天了,老实说,我很难过。你们能提供的任何帮助将不胜感激。

这是 ListFragment 的代码:

package edu.uark.csce.mobile.healthyshopper;

import android.app.ListFragment;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.CursorLoader;
import android.content.Loader;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

/**
 * A fragment representing a list of Items.
 * <p />
 * <p />
 * Activities containing this fragment MUST implement the {@link Callbacks}
 * interface.
 */
public class ViewFragment extends ListFragment implements
        LoaderCallbacks<Cursor> {
    // Class Fields:
    private static final String TAG = "healthyshopper.ViewFragment";
    private static final int MAIN_DB_LOADER = 0;

    // In the final application, any query to the main database needs to return
    // at least these fields:
    private final String[] NECESSARY_COLUMNS = { DAOContentProvider.FOOD_DES,
            DAOContentProvider.FOOD_CALORIES, DAOContentProvider.FOOD_FAT,
            DAOContentProvider.FOOD_CARBS, DAOContentProvider.FOOD_PROTEIN };

    private final String FROM[] = {DAOContentProvider.FOOD_GROUP, DAOContentProvider.FOOD_DES,
             DAOContentProvider.FOOD_MANUFAC, DAOContentProvider.FOOD_PROTEIN,
             DAOContentProvider.FOOD_FAT, DAOContentProvider.FOOD_CARBS,
             DAOContentProvider.FOOD_CALORIES, DAOContentProvider.FOOD_SERV_SIZE};
    private final int TO[] = {R.id.fd_group, R.id.shrt_desc, 
                    R.id.manufac, R.id.protein, 
                    R.id.fat, R.id.carb,
                    R.id.cal, R.id.amt};
    private int threadMode;
    private int queryType;
    private int foodGroupId;
    private CursorLoader loader;
    private SimpleCursorAdapter listAdapter;

    // Preference Option Constants:
    private int UI_THREAD = 0;
    private int BRANCHED_THREAD = 1;
    private int ALL_ROWS = 0;
    private int SPECIFIC_FD_GROUP = 1;
    private int LIMITED_ROWS = 2;

    private OnFragmentInteractionListener mListener;

    /**
     * Mandatory empty constructor for the fragment manager to instantiate the
     * fragment (e.g. upon screen orientation changes).
     */
    public ViewFragment() {
    }

    /***************************************
     * Life cycle callbacks:
     */

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG, "in onCreate()");
        setRetainInstance(true);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState){
        super.onActivityCreated(savedInstanceState);
        if(savedInstanceState == null){
            listAdapter = new SimpleCursorAdapter(getActivity(), R.layout.list_node, null, FROM, TO, 0);
            setListAdapter(listAdapter);
        }
    }

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

    @Override
    public void onResume(){
        super.onResume();

        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity()
                .getApplicationContext());

        Log.d(TAG, preferences.getString("THREADING_MODE", "BLANK"));

        //Load testing preferences:
        threadMode = Integer.valueOf(preferences.getString("THREADING_MODE","0"));
        queryType = Integer.valueOf(preferences.getString("QUERY_TYPE", "0"));
        foodGroupId = Integer.valueOf(preferences.getString("FOOD_GROUP", "0")); // Default

        if (threadMode == BRANCHED_THREAD) {
            loader = (CursorLoader) getLoaderManager().initLoader(
                    MAIN_DB_LOADER, null, this);
        } else {
            String[] projection = null;
            String selection = null;
            if (queryType == SPECIFIC_FD_GROUP) {
                Log.d(TAG, "Query Type: " + (getResources().getStringArray(R.array.query_type_select))[queryType]);
                selection = DAOContentProvider.FOOD_GROUP + " = " + foodGroupId;
            } else if (queryType == LIMITED_ROWS) {
                projection = NECESSARY_COLUMNS;
            }
            /*This is for testing only.  Ordinarily, you should NEVER perform Db operations on the UI thread.*/
            listAdapter.swapCursor(getActivity().getContentResolver().query(
            DAOContentProvider.CONTENT_URI, projection, selection, null, null));
        }
    }

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

    }

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

    @Override 
    public void onDestroyView(){
        super.onDestroyView();
        Log.e(TAG, "in onDestroyView()");
        setListAdapter(null);
        listAdapter.swapCursor(null);
        listAdapter = null; 

    }

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

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

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);

        if (null != mListener) {
        }
    }

    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated to
     * the activity and potentially other fragments contained in that activity.
     * <p>
     * See the Android Training lesson <a href=
     * "http://developer.android.com/training/basics/fragments/communicating.html"
     * >Communicating with Other Fragments</a> for more information.
     */
    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        public void onFragmentInteraction(String id);
    }

    /**
     * LoaderManager Callbacks;
     */

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        switch (id) {
        case MAIN_DB_LOADER:
            String[] projection = null;
            String selection = null;
            if (queryType == SPECIFIC_FD_GROUP) {
                Log.d(TAG,
                        "Query Type: "
                                + (getResources()
                                        .getStringArray(R.array.query_type_select))[queryType]);
                selection = DAOContentProvider.FOOD_GROUP + " = " + foodGroupId;
            } else if (queryType == LIMITED_ROWS) {
                projection = NECESSARY_COLUMNS;
            }
            return new CursorLoader(getActivity(),
                    DAOContentProvider.CONTENT_URI, projection, selection,
                    null, null);
        default:
            return null;
        }
    }

    @Override
    public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) {
        listAdapter.swapCursor(arg1);
        listAdapter.notifyDataSetChanged();
    }

    @Override
    public void onLoaderReset(Loader<Cursor> arg0) {
        listAdapter.swapCursor(null);
        listAdapter.notifyDataSetChanged();
    }

}

这里是其关联活动的代码:

package edu.uark.csce.mobile.healthyshopper;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class TestingActivity extends Activity implements ViewFragment.OnFragmentInteractionListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_testing);
        ViewFragment list = new ViewFragment();
        getFragmentManager().beginTransaction().add(R.id.test_layout, list).commit();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.testing, menu);
        return true;
    }

    @Override
    public void onFragmentInteraction(String id) {
        // TODO Auto-generated method stub

    }

}

【问题讨论】:

    标签: android android-listfragment android-cursoradapter


    【解决方案1】:

    您在片段中使用了setRetainInstance(true);。这使得片段在重新创建活动时被保留和重用。

    您可以在这个问题中阅读更详细的描述:Further understanding setRetainInstance(true)

    【讨论】:

    • setRetainInstance() 是我最近在尝试解决该问题时添加的内容。实际问题在我添加之前就存在了。
    • 我还不能查看链接。直到我回到我的电脑前,我才能做到这一点,这可能需要大约一个小时。
    • 我知道发生了什么。我忘记在 TestingActivity.onCreate() 中包含一个健全性检查,以查看 savedInstanceState 是否为空。它保留了所有先前的片段,同时还创建了一个新片段。 @Szymon,感谢您的帮助。我也感谢您与我分享链接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-24
    • 2015-03-11
    • 1970-01-01
    • 1970-01-01
    • 2013-12-22
    • 1970-01-01
    相关资源
    最近更新 更多