Question

I am developing an app which uses 3 fragments, (which are actual pages). One fragment is used as an listener, and on two others data is being downloaded, and then set to textviews. Everything was working fine, until i thought that it would be cool if fragment view would update/refresh immediately after async is finished. Problem is that it throws me nullpointer exceptions, every time I try to do something with updating my fragment.

BTW. I think I might be taking wrong approach with this type of fragments management, but it actually is working, and I want just a small cool feature, I thought that maybe I don't need to rewrite my whole program.

So this is mine mainActivity.java

public class MainActivity extends FragmentActivity {

//some uninportant initalizations



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

    // 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.setOffscreenPageLimit(3);
    mViewPager.setAdapter(mSectionsPagerAdapter);
    mViewPager.setCurrentItem(1);
    Autogidas agidas = new Autogidas();


}

public class SectionsPagerAdapter extends FragmentStatePagerAdapter {

    public SectionsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = new Pagrindinis();

        switch (position) {
        case 0:         
            return fragment = new Autogidas();
        case 1:
            return fragment = new Pagrindinis();
        case 2:
            return fragment = new AutoPlius();
        default:
            break;
        }
        return fragment;
    }


    @Override
    public int getCount() {
        // Show 3 total pages.
        return 3;
    }




    @Override
    public CharSequence getPageTitle(int position) {
        Locale l = Locale.getDefault();
        switch (position) {
        case 0:
            return getString(R.string.title_section1).toUpperCase(l);
        case 1:
            return getString(R.string.title_section2).toUpperCase(l);
        case 2:
            return getString(R.string.title_section3).toUpperCase(l);
        }
        return null;
    }

}

}

public class Autogidas extends Fragment {

TextView dummyTextViewA;
MainActivity mActivity;
String textToSet;
Context cont;
StringBuffer c;
MySQLiteHelper db;
SharedPreferences prefs;
View rootView;
ArrayList<Car> cars;

@Override
public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
}

public void setDb(Context con) {
    db = new MySQLiteHelper(con);
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    rootView = inflater.inflate(R.layout.autogidas, container, false);
    dummyTextViewA = (TextView) rootView.findViewById(R.id.section_label);
    cont = getActivity();
    setDb(cont.getApplicationContext());
    dummyTextViewA.setText("");
    setTextView();//function to return new data from database
    mActivity = new MainActivity();
    Log.i("onCreateView", "onCreateView");
    return rootView;

}

@Override
public void onSaveInstanceState(Bundle outState) {

    super.onSaveInstanceState(outState);
    Log.v("saveInstaceState", "In frag's on save instance state ");

    outState.putString("textView", dummyTextViewA.toString());

}

@Override
public void onViewStateRestored(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onViewStateRestored(savedInstanceState);

    Log.v("restored", "Inside of onRestoreInstanceState");
    if (savedInstanceState != null) {
        dummyTextViewA.setText(savedInstanceState.getString("textView"));
        ;
    }
}

public Context conts(Context con) {
    return cont = con;
}


public void sendNotif(Context con, String data) {
    CheckNetwork.sendNotification(con, data);
}

public void download() {
    //function to start asynctask

}

private class DownloadFilesTask extends AsyncTask<Void, Void, String> {

    @Override
    protected void onPreExecute() {

        super.onPreExecute();

    }

    private boolean checkIfPromoted() {
        //asynctaskstuff
    }

    @Override
    protected String doInBackground(Void... params) {

        //even more asynctask stuff

        }
        return textToSet;
    }

    @Override
    protected void onPostExecute(String result) {


        Autogidas agidas = new Autogidas();
        agidas.getFragmentManager().beginTransaction().detach(agidas).commit();
        agidas.getFragmentManager().beginTransaction().attach(agidas).commit();

        super.onPostExecute(result);

    }

}

}

ALSO fragment which is used as a trigger to start asynctask

 public class Pagrindinis extends Fragment {  
            /** 
             * The fragment argument representing the section number for this 
             * fragment. 
             */  
            public static final String ARG_SECTION_NUMBER = "section_number";  

            public void DummySectionFragment() {  
            }  

            Context cont;
            TextView dummyTextView;
            Button pradeti; 
            Fragment Autogidas;
            @Override  
            public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
                View rootView = inflater.inflate(R.layout.pagrindinis, container, false);  
                dummyTextView = (TextView) rootView.findViewById(R.id.section_label);  
                dummyTextView.setText("Pagrindinis :)");  
                pradeti = (Button) rootView.findViewById(R.id.pradeti);
                pradeti.setOnClickListener(new gidasListener());
                cont = getActivity();
                return rootView;  
            }  

            @Override
            public void onSaveInstanceState(Bundle outState) {

                super.onSaveInstanceState(outState);
                Log.v("saveInstaceState", "In frag's on save instance state ");

                outState.putString("textView", dummyTextView.toString());

            }

            @Override
            public void onViewStateRestored(Bundle savedInstanceState) {
                // TODO Auto-generated method stub
                super.onViewStateRestored(savedInstanceState);

                Log.v("restored", "Inside of onRestoreInstanceState");
                if(savedInstanceState!=null){
                dummyTextView.setText(savedInstanceState.getString("textView"));;
                }
            }


            public class gidasListener implements OnClickListener {

                @Override
                public void onClick(View v) {

                    // TODO Auto-generated method stub

                    Log.d("pliusListener", "Button Clicked");
                    Autogidas agidas = new Autogidas();
                    AutoPlius aplius = new AutoPlius();
                    agidas.AddUrls(cont.getApplicationContext());
                    agidas.conts(cont.getApplicationContext());
                    agidas.setDb(cont.getApplicationContext());
                    aplius.AddUrls(cont.getApplicationContext());
                    aplius.conts(cont.getApplicationContext());
                    aplius.setDb(cont.getApplicationContext());
                    if (CheckNetwork.isInternetAvailable(cont.getApplicationContext())) {
                        agidas.download();
                        aplius.download();
                        Log.d("download", "download" );


                    } else {
                        dummyTextView.setText("Prisijunkite prie interneto");
                    }

                }
            }
        }

++LOGCAT:

04-22 19:49:24.810: W/dalvikvm(26354): threadid=1: thread exiting with uncaught exception (group=0x40a8ca20)
04-22 19:49:24.830: E/AndroidRuntime(26354): FATAL EXCEPTION: main
04-22 19:49:24.830: E/AndroidRuntime(26354): java.lang.NullPointerException
04-22 19:49:24.830: E/AndroidRuntime(26354):    at com.example.carseeker.Autogidas$DownloadFilesTask.onPostExecute(Autogidas.java:303)
04-22 19:49:24.830: E/AndroidRuntime(26354):    at com.example.carseeker.Autogidas$DownloadFilesTask.onPostExecute(Autogidas.java:1)
04-22 19:49:24.830: E/AndroidRuntime(26354):    at android.os.AsyncTask.finish(AsyncTask.java:602)
04-22 19:49:24.830: E/AndroidRuntime(26354):    at android.os.AsyncTask.access$600(AsyncTask.java:156)
04-22 19:49:24.830: E/AndroidRuntime(26354):    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:615)
04-22 19:49:24.830: E/AndroidRuntime(26354):    at android.os.Handler.dispatchMessage(Handler.java:99)
04-22 19:49:24.830: E/AndroidRuntime(26354):    at android.os.Looper.loop(Looper.java:137)
04-22 19:49:24.830: E/AndroidRuntime(26354):    at android.app.ActivityThread.main(ActivityThread.java:4424)
04-22 19:49:24.830: E/AndroidRuntime(26354):    at java.lang.reflect.Method.invokeNative(Native Method)
04-22 19:49:24.830: E/AndroidRuntime(26354):    at java.lang.reflect.Method.invoke(Method.java:511)
04-22 19:49:24.830: E/AndroidRuntime(26354):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:787)
04-22 19:49:24.830: E/AndroidRuntime(26354):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:554)
04-22 19:49:24.830: E/AndroidRuntime(26354):    at dalvik.system.NativeStart.main(Native Method)

I am dealing with this problem for last 5 hours, and I just don't see how I could deal with it.

So maybe you could help me saying where and which methods I should place. I think the best approach is to use fragment attach/detach, but using this just send nullpointer exception. If you could help me with it I would be very grateful.

Was it helpful?

Solution 2

Okay, i have fixed all my problems by all.

If someone is struggling with dynamic fragment transactions don't forget to programatically add your fragment in your activity just like.

FragmentTransaction ftransc=getSupportFragmentManager().beginTransaction();
        Autogidas myautogidas=new Autogidas();
        Pagrindinis pagr = new Pagrindinis();
        ftransc.add(viewPager.getId(), myautogidas, "FirstFragment");

ftransc.commit();

I don't know actually why, because my whole app was working like a charm, but you just need to do it.

Even when your fragments are added, you might actually want to update data in your fragment when, for example, you ASyncTask finishes. It's easy to do it!

I have found a simple method and put it in my Fragment:

public void refreshData(ArrayList<Car> data) {
        viewPager = MainActivity.getAppPager();
        Log.d("start", "refresh");
        TabsPagerAdapter sk = new TabsPagerAdapter(getFragmentManager());
        viewPager.setAdapter(sk);
        cars = new ArrayList<Car>(data);
        StringBuffer c = new StringBuffer();
        for (Car car : cars) {

            c.append(car + "\n");
        }
        tv.setText(c.toString());
        viewPager.getAdapter().notifyDataSetChanged();

    }

and called it from my ASyncTask:

MySQLiteHelper db = new MySQLiteHelper(MainActivity.getAppContext());
            ArrayList<Car> refreshedArray = db.newCars("agidas");
            Autogidas gidas = (Autogidas) getFragmentManager()
                    .findFragmentByTag("FirstFragment");
            if (gidas != null) {
                gidas.refreshData(refreshedArray);
                Log.d("Fragment", "found");
            }

I was struggling with notifyDataSetChanged(); - you have to call it everytime you want to inform your pager that fragment should be updated. But it isn't that easy.

First of all override your getItemPosition like that - (its really not efficient, but does its job)

@Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

even after that calling notifydatasetchanged(); won't do anything.

1.You have to get your viewPager from your Acitivty:

public static ViewPager getAppPager() {
        return viewPager;
    }

and from there just check my refreshData() method.

I think i don't have to pass whole arrayList, as I am getting it right from database, and onpostexecute is just used as a trigger to update my fragment.

Thats it!:)

OTHER TIPS

In your onPostExecute():

Autogidas agidas = new Autogidas();
agidas.getFragmentManager().beginTransaction().detach(agidas).commit();
agidas.getFragmentManager().beginTransaction().attach(agidas).commit();

I think you're trying to detach the previous fragment (created in gidasListener) also with the name of agidas and detach the new fragment (current agidas). Is this the case? If so, I guess you could possibly use

getFragmentManager().detach(Autogidas.this).commit()

to get the reference to the current fragment (one you're trying to detach), though I don't know what will detaching a current fragment from itself do.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top