簡體   English   中英

Android GridView、AsyncTask 和屏幕旋轉

[英]Android GridView, AsyncTask and screen rotation

我在處理活動中的屏幕旋轉和AsyncTask遇到問題。 問題是:我有一個MainActivity里面有一個PostersFragment ,它管理布局。 在它里面有一個GridView來填充一些由AsyncTask獲取的圖像。 當我旋轉設備它messess了,我可以看到一個舊GridView實際背后GridView
這肯定是一個與重新創建活動有關的問題,我在setRetainInstance(true)搜索了很多並找到了setRetainInstance(true)方法,我試圖在我的片段中調用它,但沒有任何改變。 這是MainActivity代碼:

public class MainActivity extends ActionBarActivity {
private final String POSTERSFRAGMENT_TAG ="PFTG";
private DrawerLayout mDrawer;
private ListView mDrawerListView;
private Toolbar toolbar;
private ActionBarDrawerToggle mDrawerToggle;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    getFragmentManager().beginTransaction().add(R.id.frame_container, new PostersFragment(), POSTERSFRAGMENT_TAG).commit();
    String[] drawerChoices = getResources().getStringArray(R.array.drawer_choices_array);

    mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    mDrawerListView = (ListView) findViewById(R.id.left_drawer);
    mDrawerListView.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, drawerChoices));
    mDrawerListView.setOnItemClickListener(new DrawerItemClickListener());
    toolbar = (Toolbar) findViewById(R.id.main_activity_toolbar);
    if(toolbar!=null){
        toolbar.setTitle(getResources().getString(R.string.app_name));
        setSupportActionBar(toolbar);
    }

    mDrawerToggle = new ActionBarDrawerToggle(this,mDrawer,toolbar,R.string.drawer_open,R.string.drawer_close){
        @Override
        public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);
        }

        @Override
        public void onDrawerClosed(View drawerView) {
            super.onDrawerClosed(drawerView);
        }
    };
    mDrawer.setDrawerListener(mDrawerToggle);
}

private class DrawerItemClickListener implements ListView.OnItemClickListener{
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id){
        String x =parent.getItemAtPosition(position).toString();

        if(x.equals(getString(R.string.trending_drawer_option))) {
            PostersFragment fragment = new PostersFragment();
            getFragmentManager().beginTransaction().replace(R.id.frame_container, fragment).commit();
            mDrawer.closeDrawer(mDrawerListView);
        }
        if(x.equals(getString(R.string.bookmarked_drawer_option))){
            BookmarksFragment fragment = new BookmarksFragment();
            getFragmentManager().beginTransaction().replace(R.id.frame_container,fragment).commit();
            mDrawer.closeDrawer(mDrawerListView);
        }
        if(x.equals(getString(R.string.settings_drawer_option))){
            mDrawer.closeDrawer(mDrawerListView);
            Intent intent = new Intent(getApplicationContext(),SettingsActivity.class);
            startActivity(intent);
        }

    }
}

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    mDrawerToggle.syncState();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    mDrawerToggle.onConfigurationChanged(newConfig);
}

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    boolean drawerOpen = mDrawer.isDrawerOpen(mDrawerListView);
    return super.onPrepareOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if(mDrawerToggle.onOptionsItemSelected(item))
        return true;
    return super.onOptionsItemSelected(item);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    return true;
}

}

PostersFragment代碼:

public class PostersFragment extends android.app.Fragment {

public static final int MAX_PAGES = 50;
public int mPagesLoaded = 0;
private ImageAdapter mImages;
public boolean mIsLoading = false;
public TextView loadingText;
private SharedPreferences sharedPrefs;
private SharedPreferences.OnSharedPreferenceChangeListener spChanged;

public PostersFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    mImages = new ImageAdapter(getActivity());
    View view = inflater.inflate(R.layout.fragment_main,container,false);
    loadingText = (TextView) view.findViewById(R.id.loadingTextView);
    loadingText.setVisibility(View.GONE);
    sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
    spChanged = new SharedPreferences.OnSharedPreferenceChangeListener() {
        @Override
        public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
            mImages.clear();
            mPagesLoaded=0;
        }
    };

    sharedPrefs.registerOnSharedPreferenceChangeListener(spChanged);
    initGrid(view);
    startLoading();
    return view;
}

private void startLoading()
{
    if(mPagesLoaded>=MAX_PAGES)
        return;
    if(mIsLoading==true)
        return;

    mIsLoading=true;
    if(loadingText!=null)
        loadingText.setVisibility(View.VISIBLE);

    new FetchPageTask().execute(mPagesLoaded + 1);
}

private void stopLoading()
{
    if(mIsLoading==false)
        return;

    if(mIsLoading==true)
        mIsLoading=false;

    if(loadingText!=null)
        loadingText.setVisibility(View.GONE);
}
private void initGrid(View view)
{
    GridView gridView = (GridView) view.findViewById(R.id.gridView);
    if(gridView==null)
        return;

    gridView.setAdapter(mImages);
    gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
            ImageAdapter adapter = (ImageAdapter) parent.getAdapter();
            Movie movie = adapter.getItem(position);

            if (movie == null)
                return;

            //intent to be launched
            Intent intent = new Intent(getActivity(),DetailActivity.class);
            intent.putExtra(Movie.EXTRA_MOVIE,movie.toBundle());
            getActivity().startActivity(intent);
        }

    });

    gridView.setOnScrollListener(new AbsListView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {

        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        int lastScreen = firstVisibleItem + visibleItemCount;
            if(lastScreen == totalItemCount)
                startLoading();
        }
    });

}


private class FetchPageTask extends AsyncTask<Integer,Void,Collection<Movie>> {
    public final String LOG_TAG = FetchPageTask.class.getSimpleName();

    @Override
    protected Collection<Movie> doInBackground(Integer... params) {
        if (params.length == 0)
            return null;

        int page = params[0];

        HttpURLConnection urlConnection = null;
        BufferedReader reader = null;
        String responseJsonStr = null;

        try {
            final String API_BASE_URL = "http://api.themoviedb.org/3/movie/";
            final String API_PARAM_PAGE = "page";
            final String API_PARAM_KEY = "api_key";
            final String API_SORTING = sharedPrefs.getString(getString(R.string.pref_sorting_key),getString(R.string.pref_sorting_default_value));

            Uri builtUri = Uri.parse(API_BASE_URL).buildUpon()
                    .appendPath(API_SORTING)
                    .appendQueryParameter(API_PARAM_PAGE, String.valueOf(page))
                    .appendQueryParameter(API_PARAM_KEY, getString(R.string.my_api_key))
                    .build();
            Log.d(LOG_TAG, "Query URI: " + builtUri.toString());

            URL url = new URL(builtUri.toString());

            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();

            InputStream inputStream = urlConnection.getInputStream();
            StringBuffer buffer = new StringBuffer();

            if (inputStream == null)
                return null;

            reader = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            while ((line = reader.readLine()) != null)
                buffer.append(line + "\n");

            if (buffer.length() == 0)
                return null;

            responseJsonStr = buffer.toString();

        } catch (Exception e) {
            Log.e(LOG_TAG, "Error", e);
            return null;
        } finally {
            if (urlConnection != null)
                urlConnection.disconnect();
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    Log.e(LOG_TAG, "Error closing input stream", e);
                }
            }
        }

        try {
            return fetchMoviesFromJson(responseJsonStr);
        } catch (JSONException je) {
            Log.d(LOG_TAG, "Can't parse JSON " + responseJsonStr, je);
            return null;
        }

    }


    private Collection<Movie> fetchMoviesFromJson(String jsonStr) throws JSONException {
        final String KEY_MOVIES = "results";

        JSONObject json = new JSONObject(jsonStr);
        JSONArray movies = json.getJSONArray(KEY_MOVIES);
        ArrayList<Movie> result = new ArrayList<Movie>();

        for (int i = 0; i < movies.length(); i++) {
            result.add(Movie.getMovieFromJson(movies.getJSONObject(i)));
        }
        return result;
    }

    @Override

    protected void onPostExecute(Collection<Movie> movies)
    {
        stopLoading();

        mPagesLoaded++;

        mImages.addAll(movies);
    }

}

}

我怎樣才能防止它重復? 我應該如何處理配置更改?

在 MainActivity 的onCreate中替換這一行:

getFragmentManager().beginTransaction().add(R.id.frame_container, new PostersFragment(), POSTERSFRAGMENT_TAG).commit();

if (savedInstanceState == null) {
    getFragmentManager().beginTransaction().add(R.id.frame_container, new PostersFragment(), POSTERSFRAGMENT_TAG).commit();
}

編輯:抱歉,我沒有說明為什么需要這樣做。 此檢查的目的是查看片段是否已經存在。 我們什么時候可以確認片段不存在? savedInstanceStatenull
最初,首次創建活動時, Bundlenull 當設備發生配置更改時,所有活動/片段都將被銷毀並重新創建,除了已調用setRetainInstance(true)活動/片段。 這些碎片不會被破壞。 他們只是依附於新活動……
在配置更改后重新創建 Activity 時,保留片段的實例已經存在,因此savedInstanceState不為null 因此,您檢查是否savedInstanceState == null然后才繼續添加片段以避免重復。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM