我有一个片段,我正在对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
中犯错误,例如add
或replace
片段(当设备旋转时,也会重新创建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)
。