Filling a ListView on a fragment after running Async from Activity

I have a main activity that will receive JSON data from an asynchronous URL

This is MainActivity.java

public class MainActivity extends FragmentActivity implements ActionBar.TabListener{ private ViewPager viewPager; private TabsPagerAdapter mAdapter; private ActionBar actionBar; //Tab titles private String[] tabs = {"Sermons", "More"}; private String[] sermonsList = new String[0]; //JSON URL for sermonList data private static String sermonListJSONUrl = "https://dl.dropboxusercontent.com/u/12345/index.php"; //Variable to save JSON Object private static final String JSON_KEY_SERMONS = "sermon"; private JSONObject sermonListJSONObject = null; private JSONArray sermonListJSONArray = null; SermonsFragment mSermonFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //Call JSONParser Asynchronously to get sermonList in JSON Format new callJSONParserAsync().execute(sermonListJSONUrl); //this.mSermonFragment = (SermonsFragment) getFragmentManager().findFragmentById(android.R.id.list); this.mSermonFragment = (SermonsFragment) getFragmentManager().findFragmentById(R.id.pager); //Initialization viewPager = (ViewPager) findViewById(R.id.pager); actionBar = getActionBar(); mAdapter = new TabsPagerAdapter(getFragmentManager()); viewPager.setAdapter(mAdapter); actionBar.setHomeButtonEnabled(false); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); //Adding Tabs for(String tab_name : tabs) { actionBar.addTab(actionBar.newTab().setText(tab_name).setTabListener(this)); } /** * on swiping the viewpager make respective tab selected */ viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { //on changing the page //make respected tab selected actionBar.setSelectedNavigationItem(position); } @Override public void onPageScrollStateChanged(int state) { } }); } 

This is activity_main.xml

 <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v4.view.ViewPager> 

This is SermonsFragment.java

 public class SermonsFragment extends ListFragment { private String[] sermonsList; ArrayAdapter listAdapter; String imageUrl = "https://fbcdn-sphotos-ba.akamaihd.net/" + "hphotos-ak-prn2/t1.0-9/10415605_10132423542_6220704573655530117_n.jpg"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); sermonsList = ((MainActivity)getActivity()).getSermonsList(); //ListView for the sermon list, only show if there is something in listview listAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, sermonsList); if(listAdapter.getCount() != 0) { setListAdapter(listAdapter); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_sermons, container, false); // show The Image new getSermonBannerImage((ImageView) rootView.findViewById(R.id.series_banner)) .execute(imageUrl); return rootView; } public void updateListView(String[] newData) { if(newData.length == 0) { Log.d("myTesting3", "sermonsList is Empty"); } else { Log.d("myTestingSermonFragment", newData[0]); Log.d("myTestingSermonFragment", newData[1]); } sermonsList = newData; Log.d("myTestingSermonFragment", sermonsList[1]); this.listAdapter.clear(); this.listAdapter.addAll(newData); this.listAdapter.notifyDataSetChanged(); } 

This is the fragment_sermon.xml

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#222222" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical"> <!-- Shows an image from your drawable resources --> <ImageView android:id="@+id/series_banner" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_gravity="center" android:src="@drawable/series_banner" /> <!-- Closing tag for the horizontal nested layout --> <View android:layout_width="fill_parent" android:layout_height="10dp" android:layout_marginBottom="10dp" android:background="@android:color/darker_gray"/> <ListView android:id="@android:id/list" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#ffffffff" /> <TextView android:id="@android:id/empty" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:text="No Data" /> </LinearLayout> </RelativeLayout> 

This is the TabsPagerAdapter.java tab.

 public class TabsPagerAdapter extends FragmentPagerAdapter { public TabsPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int index) { switch (index) { case 0: //Sermons fragment activity return new SermonsFragment(); case 1: //More fragment activity return new MoreFragment(); } return null; } @Override public int getCount() { //get item count - equal to number of tabs return 2; } } 

and finally this is a mistake

 07-27 16:42:27.921 1549-1555/org.myapp.myapp E/jdwp﹕ Failed writing handshake bytes: Broken pipe (-1 of 14) 07-27 16:42:29.941 1549-1549/org.myapp.myapp E/OpenGLRenderer﹕ Getting MAX_TEXTURE_SIZE from GradienCache 07-27 16:42:29.941 1549-1549/org.myapp.myapp E/OpenGLRenderer﹕ MAX_TEXTURE_SIZE: 16384 07-27 16:42:29.953 1549-1549/org.myapp.myapp E/OpenGLRenderer﹕ Getting MAX_TEXTURE_SIZE from Caches::initConstraints() 07-27 16:42:29.953 1549-1549/org.myapp.myapp E/OpenGLRenderer﹕ MAX_TEXTURE_SIZE: 16384 07-27 16:42:30.353 1549-1549/org.myapp.myapp E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: org.myapp.myapp, PID: 1549 java.lang.NullPointerException at org.myapp.myapp.MainActivity$callJSONParserAsync.onPostExecute(MainActivity.java:174) at org.myapp.myapp.MainActivity$callJSONParserAsync.onPostExecute(MainActivity.java:157) at android.os.AsyncTask.finish(AsyncTask.java:632) at android.os.AsyncTask.access$600(AsyncTask.java:177) at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5017) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595) at dalvik.system.NativeStart.main(Native Method) 

I'm not sure why there is an OpenGLRenderer error, but it has always been there since I created this application, and it has been working fine, so there is no problem (although if you can specify how to fix it, it will be Great). MainActivity.java:174 is a string on mSermonFragment.updateListView(sermonsList);

How can I make sure it is filled correctly? preferably async so that it does not block the user interface, possibly updating the list later after the completion of asynchronization.

It would be nice if you could also indicate how to do this during asynchronization, it will check if there is an Internet connection, viewing the list will show the download area, and if it does not have Internet or an empty list, it will not show any data, otherwise it will display a list

+6
source share
7 answers

Since you only have two fragments, you can track their instance persistence. Using callbacks, as suggested, is not the best option.

So, in your paging adapter:

 public class TabsPagerAdapter extends FragmentPagerAdapter { SermonsFragment mSermonsFragment; MoreFragment mMoreFragment; public TabsPagerAdapter(FragmentManager fm) { super(fm); this.mSermonsFragment = new SermonsFragment(); this.mMoreFragment = new MoreFragment(); } @Override public Fragment getItem(int index) { switch (index) { case 0: //Sermons fragment activity return mSermonsFragment; case 1: //More fragment activity return mMoreFragment; } return null; } @Override public int getCount() { //get item count - equal to number of tabs return 2; } public updateSermonsFragment(String[] data) { mSermonsFragment.updateData(data); } //i don't know what the data type managed by MoreFragment public updateMoreFragment(Object data) { mMoreFragment.updateData(data) } } 

Create a way to update the adapter in your fragment:

 public void updateData(String[] newData) { this.listAdapter.clear(); for(int i = 0; i < newData.length; i++) { this.listAdapter.add(newData[i]); } this.listAdapter.notifyDataSetChanged(); } 

Then you can call this method from onPostExecute of your AsyncTask called by your adapter:

 protected void onPostExecute(JSONObject jsonObject) { sermonListJSONObject = jsonObject; sermonListJSONArray = parseJSONObjToJSONArray(sermonListJSONObject, JSON_KEY_SERMONS); String[] sermonsList; .... // here you need set an array with the strings you parsed //here you call the new method on the adapter to update your data. mAdapter.updateSermonsFragment(sermonsList); } 

Another best practice is to define the static method newInstace(String[] data) in your fragment so that you can initialize the fragment data on the very first network call to make sure that your fragment has a data set to work with then updating as described above.

+4
source

Why you do not call / do not execute

sermonsList = ((MainActivity) getActivity ()). getSermonsList ();

in onPostExecute () for AsyncJob?

onPostExecute works in UI-Thread - so this should not be a problem

+2
source

There are many options:

  • Pass the link of your fragment to AsyncTask and update the adapter in onPostExecute .
  • Create a method in your activity and call it when AsyncTask completes. Inside this method, update the snippet.
  • Run AsyncTask inside your snippet.

An example of updating data in your fragment:

 public class SermonsFragment extends ListFragment { public void update(String[] sermonsList){ listAdapter.addAll(sermonsList); listAdapter.notifyDataSetChanged(); } } 
+1
source

It might be a topic, but I just ran into a similar handshake error using volley and https urls. here for more information.

A simple connection failure check is to trust all SSL certificates. ( This should only be used for testing! ).

Run this before the first call (fe extend Application and call the following in onCreate )

 //trust all SSL SSLCertificateHandler.nuke(); 

Trust-all-class:

 public class SSLCertificateHandler { protected static final String TAG = "NukeSSLCerts"; public static void nuke() { try { TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { X509Certificate[] myTrustedAnchors = new X509Certificate[0]; return myTrustedAnchors; } @Override public void checkClientTrusted(X509Certificate[] certs, String authType) { } @Override public void checkServerTrusted(X509Certificate[] certs, String authType) { } } }; SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String arg0, SSLSession arg1) { return true; } }); } catch (Exception e) { } } 

}

+1
source

onResume () method that you populate listview

0
source

It would be nice if I could help you, because I also encountered such a problem ...

You want to install an adapter that includes a string array provided by your synth.

create constructor in TabsPagerAdapter.class .........

  ArrayList<String> arrayList_Tab = new ArrayList<String>(); ** Constructor of the class */ public TabsPagerAdapter(FragmentManager fm, ArrayList<String> arrayList1) { super(fm); this.arrayList = arrayList1; ................ @Override public Fragment getItem(int index) { Bundle data = new Bundle(); switch (index) { case 0: SermonsFragment ment = new SermonsFragment (); data.putStringArrayList("data", arrayList); ment.setArguments(data); return ment; case 1: //More fragment activity return new MoreFragment(); } return null; } 

I did arraylist with this, but you can do it with passing an array as parameters. in your MainActivity .. add the synthesis data to the arraylist and then go to the TabsPagerAdapter class

  mAdapter = new TabsPagerAdapter(getFragmentManager()); 

change the value above to

  mAdapter = new TabsPagerAdapter(getFragmentManager(),ArrayLListgotfromAsyctask); 

now get your class in the SermonsFragment class as: -

 ArrayList<String> arrayList = new ArrayList<String>(); @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); arrayList = getArguments().getStringArrayList("data"); } 

Now you can configure arraylist on the adapter.

Good luck !!!

0
source
 public void updateData(String[] newData) { this.listAdapter.clear(); for(int i = 0; i < newData.length; i++) { this.listAdapter.add(newData[i]); } this.listAdapter.notifyDataSetChanged(); } // call this method in onPostExecute() method . By calling listAdapter.notifyDataSetChanged(); this adapter is updated with the data which comes from JSON object . 

hope it helps u :)

0
source

Source: https://habr.com/ru/post/972613/


All Articles