Reputation: 11
I have looked all night for a solution.. but I can't seem to find one that is right for my code :S. My fragment gets destroyed on rotation, I understand I have to save it in a bundle or something, but i'm too noobie to get it working. Please help, here is my code:
package com.remcoborst.mymovielibrary;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;
import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.FragmentTransaction;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends FragmentActivity implements ActionBar.TabListener {
// #5781a9
SectionsPagerAdapter mSectionsPagerAdapter;
private static Context context;
ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MainActivity.context = getApplicationContext();
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create the adapter that will return a fragment for each of the three
// primary sections of the app.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
actionBar.addTab(
actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i)).setTabListener(this)
);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public void onTabSelected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
}
@Override
public void onTabReselected(ActionBar.Tab tab,
FragmentTransaction fragmentTransaction) {
}
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a DummySectionFragment (defined as a static inner class
// below) with the page number as its lone argument.
if(position == 0){
// My Movies class
Fragment fragment = new MyMovies();
return fragment;
}else{
// Add Movies
Fragment fragment = new AddMovies();
return fragment;
}
}
@Override
public int getCount() {
// Show 3 total pages.
return 2;
}
@Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return "My Movies".toUpperCase(l);
case 1:
return "Add".toUpperCase(l);
}
return null;
}
}
/**
* A dummy fragment representing a section of the app, but that simply
* displays dummy text.
*/
public static class MyMovies extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Rootview is the fragment layout, fragment_main_dummy.xml in layouts
View rootView = inflater.inflate(R.layout.fragment_main_dummy, container, false);
return rootView;
}
}
/**
* A dummy fragment representing a section of the app, but that simply
* displays dummy text.
*/
public static class AddMovies extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Rootview is the fragment layout, fragment_main_dummy.xml in layouts
final View rootView = inflater.inflate(R.layout.fragment_form, container, false);
final LinearLayout listViewData = (LinearLayout) rootView.findViewById(R.id.listViewData);
// Create button
Button bt = (Button) rootView.findViewById(R.id.addmovie);
bt.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
EditText inputfield = (EditText) rootView.findViewById(R.id.imdblink);
String sTitle = inputfield.getText().toString().trim().replace(' ', '+');
if(MainActivity.hasActiveInternetConnection(getActivity())){
try{
listViewData.removeAllViews();
LoadMovies LoadMovies = new LoadMovies(getActivity());
LoadMovies.execute("http://imdbapi.org/?title="+sTitle+"&type=json&plot=simple&limit=10&lang=en-US&release=simple&mt=M");
}catch(Exception e){
e.printStackTrace();
}
}else{
showWarning("No working internet connection found!","Please ensure that you have a working internet connection before searching for movies.",getActivity());
}
}
});
return rootView;
}
}
public static class LoadMovies extends AsyncTask<String, Void, List<LinearLayout>> {
private Context SubContext;
private ProgressDialog pd;
public LoadMovies(Context SubContext){
this.SubContext = SubContext;
}
@Override
protected void onPreExecute() {
pd = ProgressDialog.show(this.SubContext, "", "Loading. Please wait...", true);
}
@Override
protected List<LinearLayout> doInBackground(String... urls) {
StringBuilder builder = new StringBuilder(1000000);
List<LinearLayout> localArrayList = new ArrayList<LinearLayout>();
for (String url : urls) {
Log.v("URLS",url);
if(url != "" && url != null){
try {
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
HttpResponse response = client.execute(request);
InputStream in = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = null;
while((line = reader.readLine()) != null)
{
builder.append(line);
}
in.close();
String sHtml = builder.toString();
// Change json slightly...
sHtml = "{ \"Movies\": "+sHtml+" }";
JSONObject json = new JSONObject(sHtml);
JSONArray jsa = json.getJSONArray("Movies");
for(int i = 0; i < jsa.length(); i++){
JSONObject c = jsa.getJSONObject(i);
if(c.has("poster")){
String sImageUrl = c.getString("poster");
try{
ImageView imdbimg = new ImageView(this.SubContext);
URL imgUrl = new URL(sImageUrl.replaceAll(" ", "%20"));
Bitmap bmp = BitmapFactory.decodeStream(imgUrl.openConnection().getInputStream());
imdbimg.setImageBitmap(bmp);
imdbimg.setAdjustViewBounds(true);
imdbimg.setMaxHeight(200);
imdbimg.setMaxWidth(135);
imdbimg.setPadding(0, 0, 20, 0);
LinearLayout dynLL1 = new LinearLayout(this.SubContext);
LinearLayout.LayoutParams LLparams1 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
dynLL1.setOrientation(LinearLayout.VERTICAL);
dynLL1.setLayoutParams(LLparams1);
TextView textView1 = new TextView(this.SubContext);
textView1.setTextColor(Color.parseColor("#000000"));
textView1.setTextSize(18);
textView1.setPadding(0, 10, 20, 10);
textView1.setText(c.getString("title"));
TextView textView2 = new TextView(this.SubContext);
textView2.setText("Year: "+c.getString("year"));
JSONArray aRuntime = c.getJSONArray("runtime");
TextView textView3 = new TextView(this.SubContext);
textView3.setText("Length: "+aRuntime.getString(0));
dynLL1.addView(textView1);
dynLL1.addView(textView2);
dynLL1.addView(textView3);
LinearLayout dynLL2 = new LinearLayout(this.SubContext);
LinearLayout.LayoutParams LLparams2 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
LLparams2.setMargins(20, 20, 20, 20);
dynLL2.setOrientation(LinearLayout.HORIZONTAL);
dynLL2.setLayoutParams(LLparams2);
dynLL2.setBackgroundColor(Color.parseColor("#ffffff"));
dynLL2.addView(imdbimg);
dynLL2.addView(dynLL1);
localArrayList.add(dynLL2);
}catch(Exception e){
e.printStackTrace();
}
}
};
} catch (Exception e) {
e.printStackTrace();
}
}
}
return localArrayList;
}
@Override
protected void onPostExecute(List<LinearLayout> localArrayList) {
LinearLayout listViewData = (LinearLayout) ((Activity) this.SubContext).findViewById(R.id.listViewData);
for (final LinearLayout dynLL : localArrayList) {
listViewData.addView(dynLL);
}
pd.dismiss();
}
}
public static boolean hasActiveInternetConnection(Context SubContext) {
if (isNetworkAvailable(SubContext)) {
try {
HttpURLConnection urlc = (HttpURLConnection) (new URL("http://www.google.com").openConnection());
urlc.setRequestProperty("User-Agent", "Test");
urlc.setRequestProperty("Connection", "close");
urlc.setConnectTimeout(1500);
urlc.connect();
return (urlc.getResponseCode() == 200);
} catch (IOException e) {
Log.e("ERROR: ", "Error checking internet connection", e);
}
} else {
Log.d("ERROR: ", "No network available!");
}
return false;
}
private static boolean isNetworkAvailable(Context SubContext) {
ConnectivityManager connectivityManager = (ConnectivityManager) SubContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null;
}
public static void showWarning(String title, String mymessage,Context context)
{
new AlertDialog.Builder(context)
.setMessage(mymessage)
.setTitle(title)
.setCancelable(true)
.setIcon(R.drawable.warning)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//do things
}
})
.show();
}
}
Upvotes: 1
Views: 1998
Reputation: 196
these could be a long answer but best read the Fragments section at Fragments
a suggestion to clean things up use Interfaces for callbacks to the Activity from the fragment to run the AsyncTask. Keep the Fragment in a separate class. Then I would send an intent or return an ArrayList where ofMoviedata implements Parcelable. Save that list on the MainActivity's onSaveInstance callback sticking in an extra for the ArrayList. In this same place save your position for you ViewPager's selected index.
so in your @Override onCreate(Bundle savedInstancestate){ //you can check if(savedInstanceState == null){ //means fresh load do your init stuff
}else{
//means orientation change grab the stuff you want saved to recreate the UI
if(savedInstanceState.containsKey(EXTRA_LIST){
mList = savedInstanceState.getParcelableArrayList(EXTRA_LIST)
}
if(savedInstancestate.containsKey(EXTRA_INDEX){
this.mDisplayedIndex = savedInstanceState.getInt(EXTRA_DISPLAYED_INDEX);
}
}
your onSaveInstanceState will look something like the follwing:
@Override
protected void onSaveInstanceState(Bundle outState){
outState.putInt(EXTRA_DISPLAYED_INDEX, mDisplayedIndex);
outState.putParcelableArrayList(EXTRA_APPS_LIST, mList);
super.onSaveInstanceState(outState);
}
That's some basic stuff on handling orientation changes. Look at this for a better answer on actually saving the fragment during an orientation change. another answer sorry I can't help more have to get back to work. but that should help get you on your way I hope.
Upvotes: 1