可分包实现不起作用.应用仍会在设备轮换时进行网络调用



我有一个片段,我正在对API进行网络调用。我的模型实现了 Parcelable 以保存设备旋转时的状态。我已经实现了该方法,但是当设备旋转时,它仍然发出网络请求。不知何故,包裹实现不起作用。

这是我的代码

电影.java(模型)

package com.execube.genesis.model;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
/**
 * Created by Prateek Phoenix on 4/24/2016.
 */
public class Movie implements Parcelable {
    private int mId;
    private String mOriginalTitle;
    private String mTitle;
    private  String mPosterPath;
    private  String mOverview;
    private  float mVoteAverage;

    private Movie(Parcel source) {
        mId=source.readInt();
        mOriginalTitle=source.readString();
        mTitle=source.readString();
        mPosterPath=source.readString();
        mOverview=source.readString();
        mVoteAverage=source.readFloat();
    }
    public Movie() {
    }

    public int getId() {
        return mId;
    }
    public void setId(int id) {
        mId = id;
    }
    public String getOriginalTitle() {
        return mOriginalTitle;
    }
    public void setOriginalTitle(String originalTitle) {
        mOriginalTitle = originalTitle;
    }
    public String getTitle() {
        return mTitle;
    }
    public void setTitle(String title) {
        mTitle = title;
    }
    public String getPosterPath() {
        return mPosterPath;
    }
    public void setPosterPath(String posterPath) {
        mPosterPath = posterPath;
    }
    public String getOverview() {
        return mOverview;
    }
    public void setOverview(String overview) {
        mOverview = overview;
    }
    public float getVoteAverage() {
        return mVoteAverage;
    }
    public void setVoteAverage(float voteAverage) {
        mVoteAverage = voteAverage;
    }
    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mId);
        dest.writeString(mOriginalTitle);
        dest.writeString(mTitle);
        dest.writeString(mPosterPath);
        dest.writeString(mOverview);
        dest.writeFloat(mVoteAverage);
    }
    public static final Parcelable.Creator<Movie> CREATOR= new Parcelable.Creator<Movie>(){
        @Override
        public Movie createFromParcel(Parcel source) {
            return new Movie(source);
        }
        @Override
        public Movie[] newArray(int size) {
            return new Movie[0];
        }
    };

}

热门电影片段.java

package com.execube.genesis.views;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.execube.genesis.R;
import com.execube.genesis.model.Movie;
import com.execube.genesis.utils.API;
import com.execube.genesis.utils.OkHttpHandler;
import com.squareup.picasso.Picasso;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.ArrayList;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
/**
 * Created by Prateek Phoenix on 4/24/2016.
 */
public class PopularMoviesFragment extends Fragment {
    private static final String TAG = "HELLO WORLD";
    private static final String POPULAR_MOVIES_ARRAY ="popular_movies" ;
    private ArrayList<Movie> mMovies;
    private RecyclerView popularMoviesList = null;
    private View progressBarPopular = null;
    public PopularMoviesFragment() {
    //empty constructor required
    }


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(savedInstanceState!=null)
        {
            mMovies=savedInstanceState.getParcelableArrayList(POPULAR_MOVIES_ARRAY);
        }
        else {
            String url = API.BASE_URL+API.API_KEY+API.SORT_POPULARITY;
            OkHttpHandler handler= new OkHttpHandler(url, apiCallback);
            handler.fetchData();
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putParcelableArrayList(POPULAR_MOVIES_ARRAY,mMovies);//Saving state of the ArrayList to avoid the network calls.
        super.onSaveInstanceState(outState);
    }
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View content = inflater.inflate(R.layout.fragment_popular_movies,container,false);
        popularMoviesList = (RecyclerView) content.findViewById(R.id.popular_recyclerView);
        progressBarPopular = content.findViewById(R.id.progressBar_popular);
        if(getActivity().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
            popularMoviesList.setLayoutManager(new GridLayoutManager(getActivity(), 2));
        }
        else{
            popularMoviesList.setLayoutManager(new GridLayoutManager(getActivity(), 3));
        }

        PopularMoviesAdapter mAdapter = new PopularMoviesAdapter();
        popularMoviesList.setAdapter(mAdapter);
        return content;
    }

    private Callback apiCallback =  new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            //TODO show error message from here but in UI thread
        }
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            try {
                mMovies= parseItems(response.body().string());
            } catch (Exception e) {
                Log.v(TAG,"Exception caught: ",e);
            }
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    progressBarPopular.setVisibility(View.GONE);
                    popularMoviesList.setVisibility(View.VISIBLE);
                    //TODO add adapter
                }
            });
        }
    };
    private class PopularMoviesViewHolder extends RecyclerView.ViewHolder{
        private ImageView mPosterImage;
        public PopularMoviesViewHolder(View itemView) {
            super(itemView);
            mPosterImage= (ImageView)itemView.findViewById(R.id.poster);
        }
    }
    private class PopularMoviesAdapter extends RecyclerView.Adapter<PopularMoviesViewHolder>
    {

        @Override
        public PopularMoviesViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view= LayoutInflater.from(getActivity()).inflate(R.layout.movie_item,parent,false);
            return new PopularMoviesViewHolder(view);
        }
        @Override
        public void onBindViewHolder(PopularMoviesViewHolder holder, int position) {
            final Movie movie=mMovies.get(position);
            Picasso.with(getActivity()).load(API.IMAGE_URL+API.IMAGE_SIZE_185+movie.getPosterPath())
                    .into(holder.mPosterImage);
        }
        @Override
        public int getItemCount() {
            return mMovies.size();
        }
    }

    private ArrayList<Movie> parseItems( String jsonResponse) throws JSONException{
        JSONObject jsonData= new JSONObject(jsonResponse);
        JSONArray moviesJSONArray= jsonData.getJSONArray("results");
        ArrayList<Movie> Movies= new ArrayList<>();
        for (int i = 0; i <moviesJSONArray.length() ; i++) {
            Movie movie= new Movie();
            JSONObject movieJson= moviesJSONArray.getJSONObject(i);
            movie.setId(movieJson.getInt("id"));
            movie.setOriginalTitle(movieJson.getString("original_title"));
            movie.setTitle(movieJson.getString("title"));
            movie.setPosterPath(movieJson.getString("poster_path"));
            movie.setOverview(movieJson.getString("overview"));
            movie.setVoteAverage((float) movieJson.getDouble("vote_average"));

            Movies.add(movie);
        }
        return  Movies;
    }
}

OkhttpHandler.java(网络代码)

package com.execube.genesis.utils;
import okhttp3.Cache;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
/**
 * Created by Prateek Phoenix on 4/24/2016.
 */
public class OkHttpHandler {
    private String queryUrl;
    private static final String TAG = "CustomTAG1";
    private String mResponse;
    private Callback mCallback;
    public OkHttpHandler(String Url, Callback callback) {
        this.mCallback = callback;
        this.queryUrl = Url;
    }
    public void fetchData() {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(queryUrl)
                .build();
        Call call = client.newCall(request);
        call.enqueue(mCallback);

    }
}

查看页面片段.java

package com.execube.genesis.views;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.execube.genesis.R;
/**
 * Created by Prateek Phoenix on 4/24/2016.
 */
public class ViewPagerFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view= inflater.inflate(R.layout.fragment_viewpager,container,false);
        ViewPager viewPager= (ViewPager)view.findViewById(R.id.viewPager);
        TabLayout tabLayout=(TabLayout)view.findViewById(R.id.tabLayout);
        final PopularMoviesFragment fragment1= new PopularMoviesFragment();
        final TopRatedMoviesFragment fragment2= new TopRatedMoviesFragment();
        viewPager.setAdapter(new FragmentPagerAdapter(getChildFragmentManager()) {
            @Override
            public Fragment getItem(int position) {
                return position==0?fragment1:fragment2;
            }
            @Override
            public int getCount() {
                return 2;
            }
            @Override
            public CharSequence getPageTitle(int position) {
                return position==0?"POPULAR":"TOP RATED";
            }
        });
        tabLayout.setupWithViewPager(viewPager);
        return view;
    }
}

电影活动.java

package com.execube.genesis.views;
import android.graphics.Color;
import android.os.Build;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import com.execube.genesis.R;
public class MoviesActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_movies);
        View view= findViewById(R.id.viewpager_container);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            getWindow().setStatusBarColor(Color.TRANSPARENT);
        }
        FragmentManager fragmentManager= getSupportFragmentManager();
        Fragment fragment= fragmentManager.findFragmentById(R.id.viewpager_container);
        if(fragment==null)
        {
            fragment= new ViewPagerFragment();
            fragmentManager.beginTransaction()
                    .add(R.id.viewpager_container,fragment)
                    .commit();
        }

    }
}

我认为您在重新创建activity时可能会在Activity中犯错误,例如addreplace片段(当设备旋转时,也会重新创建activity)。
关于处理方向改变,你可以setRetainInstance()你的Fragment。处理运行时更改:

如果重新启动活动需要恢复大量数据、重新建立网络连接或执行其他密集型操作,则由于配置更改而完全重新启动可能会带来缓慢的用户体验。此外,您可能无法完全恢复活动状态

当安卓系统因配置而关闭您的活动时 更改,您标记为保留的活动片段不会被销毁。您可以将此类片段添加到活动中以保留有状态对象。

// this method is only called once for this fragment
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // retain this fragment
    setRetainInstance(true);
}
// find the retained fragment on activity restarts
    FragmentManager fm = getFragmentManager();
    dataFragment = (DataFragment) fm.findFragmentByTag(“data”);
    // create the fragment and data the first time
    if (dataFragment == null) {
        // add the fragment
        dataFragment = new DataFragment();
        fm.beginTransaction().add(dataFragment, “data”).commit();
        // load the data from the web
        dataFragment.setData(loadMyData());
    }

警告: 虽然可以存储任何对象,但切勿传递绑定到活动的对象,例如可绘制对象、适配器、视图或与上下文关联的任何其他对象。如果这样做,它将泄漏原始活动实例的所有视图和资源。(泄漏资源意味着您的应用程序会保留它们,并且无法对其进行垃圾回收,因此可能会丢失大量内存。

更新我不确定,但在你的情况下,你应该为你setRetainInstance() ViewPagerFragment,并且:

    // make those fragments global variable.
    PopularMoviesFragment fragment1= new PopularMoviesFragment();
    TopRatedMoviesFragment fragment2= new TopRatedMoviesFragment();

在活动中,替换以下代码:

FragmentManager fragmentManager= getSupportFragmentManager();
Fragment fragment= fragmentManager.findFragmentById(R.id.viewpager_container);
if(fragment==null)
{
    fragment= new ViewPagerFragment();
    fragmentManager.beginTransaction()
            .add(R.id.viewpager_container,fragment)
            .commit();
}

改为使用以下内容:

if(savedInstanceState == null) {
  fragment= new ViewPagerFragment();
  fragmentManager.beginTransaction()
     .add(R.id.viewpager_container,fragment)
     .commit();
}

尝试在主活动中调用onSaveInstanceState super.onSaveInstanceState(outState)

最新更新