-2

I have a ViewPager with fragments, and one of the Fragment "F" shows a ListView "ListF", with a list of categories.

This "ListF" has the ability to launch an activity "A" with another ListView "ListA" of details (Which it'd be the items of the category selected).

Then this activity has the option to launch a second activity "B" that will display the information for each item of the ListView "ListA" from activity "A"(The information of the item selected).

All the information is parsed from an xml, info for the Fragment "F", activity "A", and activity "B".

The problem that I'm having is when I try to navigate back from activity "B" to activity "A", I get a NullPointerException, stating that one of the values I passed through a bundle (from Fragment "F" to Activity "A" is null) or sort of like that.

This is my Fragment

public class DirectoryFragment extends Fragment{

DirectoryAdapter adapter;
ListView categoriesList;
Context context;
ArrayList<Category> categories=new ArrayList<Category>();
String tag="directory";
Category category;
JSONManager jmanager;

public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState){
    super.onCreateView(inflater, container, savedInstanceState);
    View view=inflater.inflate(R.layout.directory_activity, container,false);
    categoriesList=(ListView)view.findViewById(R.id.categorieslist);
    return view;
}
public DirectoryFragment(){}

public DirectoryFragment(Context context1){
    context=context1;
    jmanager=new JSONManager(getFragment(),tag);
    jmanager.execute();
}

public DirectoryFragment getFragment(){
    return this;
}

public void onAttach(Activity activity){
    super.onAttach(activity);
}
/*This is the method that displays the listview, I call it from the class that does all the parsing, since I'm using AsyncTask */
public void displayBD(final ArrayList<Category> categories){
    try {        
         if(categories==null || categories.size()==0){
         }
     } catch (Exception e) {
         e.printStackTrace();
     }
    adapter=new DirectoryAdapter(context,categories);
    categoriesList.setAdapter(adapter);
    categoriesList.setOnItemClickListener(new OnItemClickListener(){
        @Override
        public void onItemClick(android.widget.AdapterView<?> parent,
                View view, int position, long id) {
            category=categories.get(position);
            Bundle bundle=new Bundle();
            bundle.putString("title", category.getTitle());
            bundle.putString("cid",category.getCid());
            Intent intent=new Intent(context,ListingsBD.class);
            intent.putExtras(bundle);
            startActivityForResult(intent,1); ///launching Activity "A"
        }
    });
}   

}

This is the Activity "A"

 public class ListingsBD extends Activity{
ListingsBDAdapter adapter;
ListView listingList;
ArrayList<Business> listings=new ArrayList<Business>();
Context context;
String title=null,cid=null;
JSONManager jmanager;
Business listing;

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@SuppressLint("NewApi")
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    context=this;
    savedInstanceState=this.getIntent().getExtras();
    setContentView(R.layout.listings_bd_layout);
    android.app.ActionBar actionBar=getActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
    listingList=(ListView)findViewById(R.id.listingsBD);
    cid=savedInstanceState.getString("cid");// this is the line where I get the NPE
    title=savedInstanceState.getString("title");
    jmanager=new JSONManager(getFragment(),"listingsbd",cid);
    jmanager.execute();
}

public ListingsBD getFragment(){
    return this;
}

public void onPause(){
    super.onPause();
}
public void displayListings(final ArrayList<Business> listings){
    try {        
         if(listings==null || listings.size()==0){
                //Retrieve again the data list
         }
     } catch (Exception e) {
         e.printStackTrace();
     }
    adapter=new ListingsBDAdapter(context,listings);
    listingList.setAdapter(adapter);
    listingList.setOnItemClickListener(new OnItemClickListener(){
        @Override
        public void onItemClick(android.widget.AdapterView<?> parent,
                View view, int position, long id) {
            listing=listings.get(position);
            Bundle bundle=new Bundle();
            bundle.putString("name", listing.getName());
            bundle.putString("address", listing.getAddress());
            bundle.putString("zipCode",listing.getZipCode());
            bundle.putString("city", listing.getCity());
            bundle.putString("state", listing.getState());
            bundle.putString("country", listing.getCountry());
            bundle.putString("phone", listing.getPhone());
            Intent intent=new Intent(context,SingleListing.class);
            intent.putExtras(bundle); 
            startActivityForResult(intent,1);
        }
    });
}   

}

And the Activity "B"

public class SingleListing extends Activity{
String name=null;
String address=null;
String city=null;
String state=null;
String zipCode=null;
String country=null;
String phone=null;
String imgUrl=null;
TextView nameView,addressView,cityView,phoneView,mobileView,faxView,homeView,tollFreeView,emailView,websiteView;
ImageView image;

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@SuppressLint("NewApi")
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.single_listing_bd_layout);
    android.app.ActionBar actionBar=getActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
    setUp(savedInstanceState);
}

public void setUp(Bundle savedInstanceState){
    nameView=(TextView)findViewById(R.id.bd_title);
    addressView=(TextView)findViewById(R.id.bd_address);
    cityView=(TextView)findViewById(R.id.bd_city);
    phoneView=(TextView)findViewById(R.id.bd_phone);
    savedInstanceState=this.getIntent().getExtras();
    name=savedInstanceState.getString("name");
    address=savedInstanceState.getString("address");
    city=savedInstanceState.getString("city");
    state=savedInstanceState.getString("state");
    zipCode=savedInstanceState.getString("zipCode");
    country=savedInstanceState.getString("country");
    phone=savedInstanceState.getString("phone");;
    imgUrl=savedInstanceState.getString("imgUrl");
    nameView.setText(name);

    if(address.equals(""))
        addressView.setVisibility(View.GONE);
    else
        addressView.setText("Address: "+address);       
    if(city.equals(""))
        addressView.setVisibility(View.GONE);
    else
        cityView.setText(city+", "+state+", "+zipCode);
    if(phone.equals(""))
        phoneView.setVisibility(View.GONE);
    else
        phoneView.setText("Phone: "+phone);
    if(mobile.equals(""))
        mobileView.setVisibility(View.GONE);
}

public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    // Respond to the action bar's Up/Home button
    case android.R.id.home:
        NavUtils.navigateUpFromSameTask(this);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

}

This is my Log

FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.test23/com.example.test23.ListingsBD}:    java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2115)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2153)
at android.app.ActivityThread.access$700(ActivityThread.java:137)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1246)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5031)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:555)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.example.test23.ListingsBD.onCreate(ListingsBD.java:36)
at android.app.Activity.performCreate(Activity.java:5058)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2079)
... 11 more

UPDATE: This only happens when I press the back button from the action bar, If I press back from the bottom menu, Activity "A" is fully displayed and no exception is thrown. Any Help is appreciated, if you need more code or any example please let me know. Thanks!

Rosie
  • 94
  • 2
  • 11

2 Answers2

0

You are misusing savedInstanceState here, by overwriting it with this.getIntent().getExtras() :

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    context=this;
    savedInstanceState=this.getIntent().getExtras();
    ...
}

The purpose of savedInstanceState is :

savedInstanceState If the activity is being re-initialized after previously being shut down then this Bundle contains the data it most recently supplied in onSaveInstanceState(Bundle). Note: Otherwise it is null.

Since you get your exception in onCreate, this means your Activity has been destroyed and is being re-created when you navigate back to it. This means what you should do is implement onSaveInstanceState(Bundle), and store there all the parameters your activity tries to get from the intent extras.

Then you can use the following code in onCreate :

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    context=this;
    if (savedInstanceState == null)
        savedInstanceState=this.getIntent().getExtras();
    ...
}

I'm assuming that the intent extras this.getIntent().getExtras() don't survive the destruction of the activity, and that's why they are null.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • Thanks, it sounds very logic your answer, but I still getting the NPE after I changed the savedInstanceState and the onSaveInstanceState method. – Rosie Aug 14 '14 at 22:49
  • @Rosie Do you get null `savedInstanceState` in onCreate? If you implemented `onSaveInstanceState` correctly, it shouldn't be null. – Eran Aug 14 '14 at 22:53
0

After searching and Searching, I found the answer in this post https://stackoverflow.com/a/15933890/2382888. And thanks To @Eran. My app was creating a new instance of the Activity "A", even when it was only relaunching the activity, and since it was a new instance, the bundle was always null, since it was like Starting a new activity from scratch even with the onSavedInstanceState() method.

The android:launchMode="singleTop" line in the Manifest, as the Docs for Activity say: " Every time there's a new intent for a "standard" activity, a new instance of the class is created to respond to that intent."

So in this case, singleTop should be used because: "if an existing instance of the "singleTop" activity is in the target task,a new instance would be created and pushed on the stack."

Thanks for all the people who helped me and for the person who downvoted my question...

Community
  • 1
  • 1
Rosie
  • 94
  • 2
  • 11