Deepak Senapati
Deepak Senapati

Reputation: 1123

Textview is null on first click but updates on second click

It's small Android 2.2 test application using the Compatibility Package. I am trying to update the textview on another fragment on another activity on list item selection. But problem is that everytime the first click returns nullpointer exception and only on the second try its text is changing. I would like to know why is the happening and what is a good solution.

ListActivity:-

public class ListActivity extends FragmentActivity implements
    ListFragment.OnItemSelectedListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list);
    }

    @Override
    public void onItemSelected(int index) {
        // TODO Auto-generated method stub

        // Check to see if there is a frame in which to embed the
        // detail fragment directly in the containing UI.
        View detailsFrame = findViewById(R.id.detailcontainer);
        if (detailsFrame != null
                && detailsFrame.getVisibility() == View.VISIBLE) {

            DetailFragment detailFragment = (DetailFragment)    getSupportFragmentManager()
                    .findFragmentById(R.id.detailcontainer);

            if (detailFragment == null) {

                detailFragment = new DetailFragment();
            }

            // Execute a transaction, replacing any existing fragment
            // with this one inside the frame.

            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.detailcontainer, detailFragment).commit();

            detailFragment.setTextView(index);

        } else {

            // Otherwise we need to launch a new activity to display
            Intent intent = new Intent(this, DetailActivity.class);
            intent.putExtra("index", index);
            startActivity(intent);

        }
    }
}

ListFragment :-

public class ListFragment extends Fragment {

    private OnItemSelectedListener listener;

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

        String[] countries = new String[] { "India", "Pakistan", "Sri Lanka",
                "China", "Bangladesh", "Nepal", "Afghanistan", "North Korea",
                "South Korea", "Japan" };

        View view = inflater.inflate(R.layout.list_fragment, container, false);

        ListView listView = (ListView) view.findViewById(R.id.listView);

        // Populate list
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                this.getActivity(), android.R.layout.simple_list_item_1,
                countries);
        listView.setAdapter(adapter);

        // operation to do when an item is clicked
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                Toast.makeText(getActivity(), "ListItem Number " + position,
                        Toast.LENGTH_SHORT).show();


                listener.onItemSelected(position);
            }
        });

        return view;
    }

    // Container Activity must implement this interface
    public interface OnItemSelectedListener {
        public void onItemSelected(int index);
    }

    // To ensure that the host activity implements this interface
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (activity instanceof OnItemSelectedListener) {
            listener = (OnItemSelectedListener) activity;
        } else {
            throw new ClassCastException(activity.toString()
                    + " must implemenet ListFragment.OnItemSelectedListener");
        }
    }

    public void operation(int index) {

        listener.onItemSelected(index);
    }

}

Detail Activity :-

public class DetailActivity extends FragmentActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DetailFragment details;
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {

            finish();
            return;
        }

        if (savedInstanceState == null) {
            // During initial setup, plug in the details fragment.
            details = new DetailFragment();
            details.setArguments(getIntent().getExtras());
            getSupportFragmentManager().beginTransaction()
                    .add(android.R.id.content, details).commit();
        }

        Bundle extras = getIntent().getExtras();
        int index = extras.getInt("index");
        try {
            details = (DetailFragment) getSupportFragmentManager()
                    .findFragmentById(R.id.detailfragment);
            details.setTextView(index);

        } catch (NullPointerException ex) {
            ex.getStackTrace();
        }

    }

}

DetailFragment :-

public class DetailFragment extends Fragment {

    String[] capitals;

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

        super.onCreate(savedInstanceState);

        if (container == null)
            return null;

        capitals = new String[] { "delhi", "karachi", "colombo", "beijing",
                "dhaka", "katmandu", "Afghanistan", "pyongyang", "seoul",
                "tokyo" };

        View v = inflater.inflate(R.layout.detail_fragment, container, false);

        return v;
    }

    public void setTextView(int index) {

        try {
            TextView view = (TextView) getView().findViewById(R.id.detailView);
            view.setText(capitals[index]);

        } catch (NullPointerException ex) {
            ex.getStackTrace();
        }
    }

    public int getShownIndex() {
        return getArguments().getInt("index", 0);
    }
}

Update:- I am adding the detailFragment xml:-

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:background="@color/lightblue"
android:orientation="vertical" >

<TextView
    android:id="@+id/detailView"
    android:layout_width="100dp"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:text="@string/detail_frag" />

</RelativeLayout>

Upvotes: 2

Views: 1953

Answers (3)

baboo
baboo

Reputation: 2023

Instead of doing details.setTextView(index) in DetailActivity , set the value of TextView in the DetailFragment's onActivityCreated while passing the value to be set in fragments setArgument method in the Detailactivity...

  DetailsFragment details = new DetailsFragment();
  details.setArguments(getIntent().getExtras());  // pass the value of text view here

And In fragment onActivityCreated get that value via getArguments() and set it in textview..

EDIT for sending value Selected to loaded Fragment

In List Activity

  detailFragment = getFragmentbyTag
  if(detailFragment == null)
      Create Fragment and Add it and Set Arguments here as well
  else
      detailFragment.setTextView(value); // fragment already loaded no need to set arguments

if you want to replace each time and not add once and use the added/loaded fragment , use setarguments each time.... and remove previous fragment and add new fragment( with Arguments) But added once and reused is preferred instead of removing and adding/ replacing on each click

Upvotes: 1

Pratik
Pratik

Reputation: 30855

Updated2

Just initialize your TextView in onCreateView() no need to create DetailFragment with parametrize just put in comment

Check the details object whether its null or not if null initialize as you do and then called setTextView()

if(details==null)
    details = new DetailFragment(index);
else
   setTextView(index);

TextView inside onCreateView() and used their

public class DetailFragment extends Fragment {

    String[] capitals;

    int index;
    private TextView textView;

    public DetailFragment(int index){
        this.index = index;
    }

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

        super.onCreate(savedInstanceState);

        if (container == null)
            return null;

        capitals = new String[] { "delhi", "karachi", "colombo", "beijing",
                "dhaka", "katmandu", "Afghanistan", "pyongyang", "seoul",
                "tokyo" };

        View v = inflater.inflate(R.layout.detail_fragment, container, false);
        // Initialize textView
        textView = (TextView) v.findViewById(R.id.detailView);
        setTextView(index); // set value value here for first time
        return v;
    }

    public void setTextView(int index) {
        if(textView!=null)
            textView.setText(capitals[index]); 
    }

    public int getShownIndex() {
        return getArguments().getInt("index", 0);
    }
}

Upvotes: 0

AAnkit
AAnkit

Reputation: 27549

did you tried using this

TextView view = (TextView) findViewById(R.id.detailView);

instead of this

 TextView view = (TextView) getView().findViewById(R.id.detailView);

Upvotes: 0

Related Questions