I am a beginner at the android studio. I have parsed some JSON data from the server. I want to implement these data in a viewpager. I got A sample viewpager code. But when I apply these JSON data to list it shows cannot resolve constructor. My Viewpager code is below.
My JSON Fetching code
public class MainActivity extends AppCompatActivity {
// Constants
private static final String TAG = MainActivity.class.getSimpleName();
// UI Components
private VerticalViewPager mVvpMainPager;
// Other objects
private ViewPagerAdapter mPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mVvpMainPager = findViewById(R.id.activity_main_vvp_main_pager);
setupViewPager();
}
private void setupViewPager() {
mPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
for (BeanNews news : generateSampleNewsData()) {
mPagerAdapter.addFragment(PagerFragment.newInstance(news), "News " + news.getNewsId());
}
mVvpMainPager.setAdapter(mPagerAdapter);
mVvpMainPager.setOffscreenPageLimit(generateSampleNewsData().size());
}
private ArrayList<BeanNews> generateSampleNewsData() {
String url ="http://maranamassapp.cf/json_getdata.php";
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray("server_response");
for(int i = 0; i < jsonArray.length(); i++){
JSONObject ser =jsonArray.getJSONObject(i);
String creatorname = ser.getString("head");
String imageUrl = ser.getString("image");
String cat = ser.getString("content");
String postdate = ser.getString("weburl");
String dateall = ser.getString("date");
BeanNews news = new BeanNews(creatorname,imageUrl,cat,postdate,dateall);
ArrayList<BeanNews> newsList = new ArrayList<>();
newsList.add(news);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
return newsList;
}
Check this about ViewPager:
Layout manager that allows the user to flip left and right through
pages of data. You supply an implementation of a PagerAdapter to
generate the pages that the view shows.
ViewPager is most often used in conjunction with Fragment, which is a
convenient way to supply and manage the lifecycle of each page.
Now, you'll need a RecyclerView or a ListView inside ViewPager xml layout file to show the data. So, you'll need Fragment inside ViewPager, a RecyclerView || ListView inside Fragment then showing data or adding to RecyclerView adapter.
Can't actually pass list of items(from json in your case) to ViewPager to show on the view in Android.
Related
I'm new in android and want an app with viewpager. I am unable to design the viewpager in the layout. The layout fetch the data dynamatically. I want to create a matreial UI viewpager which swipes the page left or right like a paper.I have made a view which shows the data but is unable to swipe like a viewpager left or right...
The code is as below:
public class DetailNewsActivity extends AppCompatActivity {
private PullToZoomScrollViewEx scrollView;
private ArrayList<NewsItemModel> newsArr;
private TextView tvNewsTitle;
private TextView tvNewsPublishDate;
private TextView tvNewsFull;
private int newsPosition = 0;
private ImageView ivYoutubeEnable;
private SharedPreferences sharedPref;
int textSize = 16;
boolean isHighQuality = false;
private Typeface typeface;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail_news);
init();
AdView mAdView = (AdView) findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice("5745FD6726ACCBEE8324DB158D021FA5")
.build();
mAdView.loadAd(adRequest);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_detail_news, container, false);
return view;
}
private void init() {
typeface = Typeface.createFromAsset(getAssets(), "AnmolUni.ttf");
// newsArr = (ArrayList<NewsItemModel>) getIntent().getSerializableExtra("newsArray");
newsArr = AppController.getAppController().getMainNewsArr();
AppController.getAppController().setMainNewsArr(null);
newsPosition = getIntent().getIntExtra("newsPosition", 0);
findViewById(R.id.iv_back).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
findViewById(R.id.iv_share).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
generateBranchURL(newsPosition);
}
});
sharedPref = getSharedPreferences(Constants.SHARED_PREF_NAME, Context.MODE_PRIVATE);
textSize = sharedPref.getInt("text_size", 16);
isHighQuality = sharedPref.getBoolean("isHighQuality",false);
loadViewForCode();
scrollView = (PullToZoomScrollViewEx) findViewById(R.id.scroll_view);
setNewsFromArray(newsPosition);
// ((ImageView) scrollView.getZoomView().findViewById(R.id.iv_zoom)).setImageResource(android.R.drawable.arrow_down_float);
(scrollView.getZoomView().findViewById(R.id.iv_zoom)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(DetailNewsActivity.this, ImageVideoActivity.class);
intent.putExtra("viewType", "image");
if(isHighQuality)
intent.putExtra("imageArr", newsArr.get(newsPosition).getImage());
else
intent.putExtra("imageArr", newsArr.get(newsPosition).getMedium());
startActivity(intent);
}
});
DisplayMetrics localDisplayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(localDisplayMetrics);
int mScreenHeight = localDisplayMetrics.heightPixels;
int mScreenWidth = localDisplayMetrics.widthPixels;
LinearLayout.LayoutParams localObject = new LinearLayout.LayoutParams(mScreenWidth, (int) (9.0F * (mScreenWidth / 16.0F)));
scrollView.setHeaderLayoutParams(localObject);
scrollView.setParallax(true);
// scrollView.getPullRootView().findViewById(R.id.container_layout).setOnTouchListener(new OnSwipeTouchListener(DetailNewsActivity.this) {
scrollView.getPullRootView().setOnTouchListener(new OnSwipeTouchListener(DetailNewsActivity.this) {
#Override
public void onSwipeLeft() {
if (newsPosition < newsArr.size() - 1) {
newsPosition++;
setNewsFromArray(newsPosition);
} else {
CommonUtils.showToast(DetailNewsActivity.this, "No more news");
}
}
#Override
public void onSwipeRight() {
if (newsPosition > 0) {
newsPosition--;
setNewsFromArray(newsPosition);
} else {
CommonUtils.showToast(DetailNewsActivity.this, "This is the first news");
}
}
});
scrollView.setOnPullZoomListener(new PullToZoomBase.OnPullZoomListener() {
#Override
public void onPullZooming(int newScrollValue) {
Log.d("MainActivity", "onPullZooming: " + newScrollValue);
// Intent intent = new Intent(DetailNewsActivity.this, ImageVideoActivity.class);
// intent.putExtra("viewType", "image");
// intent.putExtra("imageArr", newsArr.get(newsPosition).getImage());
// startActivity(intent);
}
#Override
public void onPullZoomEnd() {
}
});
}
void setNewsFromArray(int position) {
if (position >= newsArr.size()) {
finish();
return;
}
if (!newsArr.get(position).getMedium().get(0).isEmpty()) {
if(isHighQuality)
Picasso.with(DetailNewsActivity.this).load(newsArr.get(position).getImage().get(0)).placeholder(R.drawable.logo).error(R.drawable.logo).
into((ImageView) scrollView.getZoomView().findViewById(R.id.iv_zoom));
else
Picasso.with(DetailNewsActivity.this).load(newsArr.get(position).getMedium().get(0)).placeholder(R.drawable.logo).error(R.drawable.logo).
into((ImageView) scrollView.getZoomView().findViewById(R.id.iv_zoom));
} else {
((ImageView) scrollView.getZoomView().findViewById(R.id.iv_zoom)).setImageResource(R.drawable.logo);
}
tvNewsTitle.setText(newsArr.get(position).getTitle());
tvNewsPublishDate.setText(newsArr.get(position).getPublish_dt());
//String style = "<html><body style='text-align:justify'>";
//Log.i("RAJEEV",style + newsArr.get(position).getFullnews());
tvNewsFull.setText(Html.fromHtml( newsArr.get(position).getFullnews()));
if (newsArr.get(position).getYoutube_video().isEmpty()) {
ivYoutubeEnable.setVisibility(View.GONE);
} else {
ivYoutubeEnable.setVisibility(View.VISIBLE);
}
ivYoutubeEnable.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(DetailNewsActivity.this, ImageVideoActivity.class);
intent.putExtra("viewType", "youtube");
intent.putExtra("youtube_code", newsArr.get(newsPosition).getYoutube_video());
startActivity(intent);
}
});
}
private void loadViewForCode() {
PullToZoomScrollViewEx scrollView = (PullToZoomScrollViewEx) findViewById(R.id.scroll_view);
View headView = LayoutInflater.from(this).inflate(R.layout.ptz_head_view, null, false);
View zoomView = LayoutInflater.from(this).inflate(R.layout.ptz_zoom_view, null, false);
View contentView = LayoutInflater.from(this).inflate(R.layout.ptz_content_view, null, false);
scrollView.setHeaderView(headView);
scrollView.setZoomView(zoomView);
scrollView.setScrollContentView(contentView);
tvNewsTitle = (TextView) scrollView.getPullRootView().findViewById(R.id.tv_news_title);
tvNewsPublishDate = (TextView) scrollView.getPullRootView().findViewById(R.id.tv_news_publish_date);
tvNewsFull = (TextView) scrollView.getPullRootView().findViewById(R.id.tv_news_full);
tvNewsFull.setTextSize(textSize);
if (!AppController.isPunjabiSupported()) {
tvNewsTitle.setTypeface(typeface);
tvNewsFull.setTypeface(typeface);
}
ivYoutubeEnable = (ImageView) scrollView.getHeaderView().findViewById(R.id.iv_youtube_header);
}
void generateBranchURL(final int newsPosition) {
// String imageUrl = "";
// if (newsArr.get(newsPosition).getMedium().size() <= 1)
// imageUrl = newsArr.get(newsPosition).getMedium().get(0);
BranchUniversalObject branchUniversalObject = new BranchUniversalObject()
.setCanonicalIdentifier("NewsDetails")
///.setCanonicalUrl("https://branch.io/deepviews")
//.setTitle("" + newsArr.get(newsPosition).getTitle())
//.setContentDescription("" + newsArr.get(newsPosition).getIntro())
//.setContentImageUrl("" + imageUrl)
// You use this to specify whether this content can be discovered publicly - default is public
.setContentIndexingMode(BranchUniversalObject.CONTENT_INDEX_MODE.PUBLIC);
// Here is where you can add custom keys/values to the deep link data
//.addContentMetadata("property1", "blue")
//.addContentMetadata("property2", "red");
LinkProperties linkProperties = new LinkProperties()
.addControlParameter("$desktop_url", "http://www.newsnumber.com/news/share/" + newsArr.get(newsPosition).getFn_id())
.addControlParameter("$ios_url", "itms-apps://itunes.apple.com/us/app/newsnumber/id1022442357?mt=8")
.addControlParameter("NewsId", "" + newsArr.get(newsPosition).getFn_id())
.addControlParameter("CatId", "" + newsArr.get(newsPosition).getCat_id())
.addControlParameter("$og_title", newsArr.get(newsPosition).getTitle())
.addControlParameter("$og_description", newsArr.get(newsPosition).getIntro())
.addControlParameter("$og_image_url", newsArr.get(newsPosition).getImage().get(0))
.addControlParameter("$twitter_title", newsArr.get(newsPosition).getTitle())
.addControlParameter("$twitter_description", newsArr.get(newsPosition).getIntro())
.addControlParameter("$twitter_image_url", newsArr.get(newsPosition).getImage().get(0))
;
branchUniversalObject.generateShortUrl(this, linkProperties, new Branch.BranchLinkCreateListener() {
#Override
public void onLinkCreate(String url, BranchError error) {
if (error == null) {
Log.i("MyApp", "got my Branch link to share: " + url);
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, "News Number\n");
sharingIntent.putExtra(Intent.EXTRA_TEXT, url);
startActivity(Intent.createChooser(sharingIntent, "Share via"));
}
}
});
}
}
can anyone help??
thanks in advance.
It seems like you might be trying to make a new Activity for each "page" of a ViewPager. The Android support library already has their own ViewPager that uses fragments.
You basically need three things to use a ViewPager:
The ViewPager itself
An adapter for the ViewPager
The fragment that will be used in the ViewPager (esentially the "template" that will be used for each "page" in the ViewPager)
First, we'll create the fragment. This is just a simple example that uses only one TextView, but it will work for any amount of views and data. You'll notice that static method "newInstance()" that creates and returns an instance of this fragment. Google recommends using this method to instantiate new Fragments for a ViewPager as it makes passing data to the fragment much easier. All fragments have a "setArguments()" method that lets you pass in a Bundle when you instantiate it with whatever data you want. The method "getArguments()" can be used to access that bundle and get the values out of it in onCreate() or onCreateView(). This is how you pass in an object or objects to bind its data to the views. In this example, were just passing in a String and setting that String to a TextView. You'll see how it's used when we create the adapter for the ViewPager.
//You should be using android.support.v4.app.Fragment here
public class ExampleFragment extends Fragment {
private static final String DAY_NAME_KEY = "day_name";
private TextView dayName;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.fragment_example, container, false);
dayName = (TextView) fragmentView.findViewById(R.id.day_name);
return fragmentView;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//Set the name of the day to the dayName TextView
String day = getArguments().getString(DAY_NAME_KEY);
dayName.setText(day);
}
public static ExampleFragment newInstance(String day) {
Bundle bundle = new Bundle();
bundle.putString(DAY_NAME_KEY, day);
ExampleFragment fragment = new ExampleFragment();
fragment.setArguments(bundle);
return fragment;
}
}
Now, we need to make an adapter that will create the views when the ViewPager is swiped. You need to extend either FragmentPagerAdapter or FragmentStatePagerAdapter. FragmentPagerAdapter is used for a small number of static fragments and it will use more memory. So you only want to use this if you have 4 or 5 pages and aren't adding any more dynamically.
For your case, it sounds like you want to swipe through a variable number of pages that are dynamically added, so you want to use FragmentStatePagerAdapter. It's optimized for memory efficiency and it will handle the saving and restoring of the fragments' state for you.
The adapter is simple.
First, you need to make your constructor match the super class's constructor. What that means is that your constructor must have a FragmentManager parameter. All you do with that is pass it to the super class. (You'll see below.)
Secondly, you have to implement just 2 methods from the FragmentStatePagerAdapter class:
public Fragment getItem(int position)
and
public int getCount()
getItem will be automatically called by the ViewPager when it is swiped. You just have to tell it what type of fragment to return. We'll be using the newInstance() method from the ExampleFragment class here.
getCount is the number of views that your ViewPager will be using. For example, I will have an ArrayList that will contain 7 strings (one for each day of the week). I want each one of those strings to be displayed on a different page of my ViewPager. So I'm just going to return the size of the ArrayList for this method.
Here's the class:
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
//A reference to the array of data that will be used to populate
//each fragment. In this case it's an array of Strings, but it
//could be any type of object. The Strings within this array are what
//we'll be passing to the newInstance() method of each fragment.
private ArrayList<String> days;
//Constructor must take a FragmentManager to match the superclass.
public ViewPagerAdapter(FragmentManager fm, ArrayList<String> days) {
//All you have to do with the fragment manager is pass it to super
super(fm);
//The array will be passed in when we create the Adapter in our Activity
this.days = days;
}
#Override
public Fragment getItem(int position) {
/*
Automatically called when another page is needed.
The adapter will keep track of the position of the current page
so the first time this is called, it will be 0, then when a
swipe occurs, it will be one. If it is swiped backward, it will go back to 0.
So when the position is 0, a new Fragment will be created and the
String at days.get(0) ("Monday") will be passed to it.
*/
return ExampleFragment.newInstance(days.get(position));
}
#Override
public int getCount() {
return days.size();
}
}
Now we just have to set the adapter for the ViewPager in our Activity and it will automatically handle swipes for us.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayList<String> daysOfWeek = new ArrayList<>();
daysOfWeek.add("Monday");
daysOfWeek.add("Tuesday");
daysOfWeek.add("Wednesday");
daysOfWeek.add("Thursday");
daysOfWeek.add("Friday");
daysOfWeek.add("Saturday");
daysOfWeek.add("Sunday");
ViewPager pager = findViewById(R.id.view_pager);
//Pass the activity's fragmentmanager by calling getSupportFragmentManager().
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager(), daysOfWeek);
pager.setAdapter(adapter);
}
}
This is what we get (I've added some padding and color to make it clear):
As for changing the way the pages "turn" (for example, like a newspaper), you need to look into PageTransformer
I have implemented tabs functionality via SmartTabLayout library in my android application. At present I have used same fragment as viewpager for both of my tabs. Since, the only difference is the view is that sorting of listitems. Below is my HomeActivity code:
HomeActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
final ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
final SmartTabLayout viewPagerTab = (SmartTabLayout) findViewById(R.id.viewpagertab);
viewPagerTab.setCustomTabView(this);
FragmentPagerItems pages = new FragmentPagerItems(this);
pages.add(FragmentPagerItem.of("Test1", SampleFragment.class));
pages.add(FragmentPagerItem.of("Test2", SampleFragment.class));
FragmentStatePagerItemAdapter adapter = new FragmentStatePagerItemAdapter(
getSupportFragmentManager(), pages);
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(0);
viewPagerTab.setViewPager(viewPager);
}
#Override
public View createTabView(ViewGroup container, int position, PagerAdapter adapter) {
LayoutInflater inflater = LayoutInflater.from(container.getContext());
View tab = inflater.inflate(R.layout.custom_tab_icon_and_notification_mark, container, false);
TextView txtTab=(TextView)tab.findViewById(R.id.txtTitle);
switch (position){
case 0:txtTab.setText("Test1");break;
case 1:txtTab.setText("Test2");break;
default:throw new IllegalStateException("Invalid pos - "+ position);
}
return tab;
}
My SampleFragment.java is as below wherein I do some server request for data and update the listview adapter.
SampleFragment.java
List<Items> lstItems=new ArrayList<>();
static ItemListAdapter mAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view= inflater.inflate(R.layout.fragment_sample, container, false);
ListView lstviewItems = (ListView) view.findViewById(R.id.lstItems);
int position = FragmentPagerItem.getPosition(getArguments());
View emptyView=view.findViewById(R.id.emptyList);
lstviewItems.setEmptyView(emptyView);
mAdapter = new ItemsListAdapter(getActivity(),lstItems);
lstviewItems.setAdapter(mAdapter);
switch (position){
case 0:
//JsonObjectRequest
loadItems();
break;
case 1:
//sort the loaded items
break;
}
return view;
}
private void loadItems(){
try {
JsonArrayRequest request = new JsonArrayRequest(Request.Method.GET,url, null,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
lstItems.clear();
for (int i = 0; i < response.length(); i++) {
//Add item to lstItems
}
mAdapter.notifyDataSetChanged();
}
}
});
testApp.getInstance().addToRequestQueue(request);
} catch (Exception ex) {
ex.printStackTrace();
}
}
But even after mAdapter.notifyDataSetChanged() the listview in the current viewPager tab i.e. Test1 tab is not getting refreshed. Whereas when I navigate to Test2 tab, I can see the changes in the listview, where is data has been loaded properly. Below is the screenshot for 2 different tabs.
I've also searched for this problem and found other solution which did not work for me. One of the solution being, adding a refresh method in ItemsAdapter as below:
public void refresh(List<Items> items)
{
this.items = items;
notifyDataSetChanged();
}
and instead of mAdapter.notifyDataSetChanged() I used mAdapter.refresh(lstItems);. But unfortunately it did not work either. How can I possibly overcome this. Please let me know if I have to add furthermore details on this.
I think your problem is here:
mAdapter = new ItemsListAdapter(getActivity(),lstItems);
You create a new instance of ItemsListAdapter and bind it to the listview with
lstviewItems.setAdapter(mAdapter);
The problem is that this adapter is static. So if you create a new instance you destroy the old adapter and the listview of the other tab has not the adapter anymore that updates your data.
EDIT:
I'd recommend to load the data on a central place. Add the response (your data objects) to a manager class. Then implement on every view which using this data a callback (lets say JsonDataChangedCallback). Register the classes which implementing the callback to the manager with Manager.getInstance().registerCallback(). Then every time your data is changed call updateCallbacks() in your manager and all views will be updated. That's the way implemented that process in my app and it works.
Sample Code:
public class CDMMovieManager {
private CDMMovieManager() {
m_Movies = new ArrayList<>();
m_MovieChangedCallbacks = new ArrayList<>();
}
public static synchronized CDMMovieManager getInstance() {
if(ms_Instance == null)
ms_Instance = new CDMMovieManager();
return ms_Instance;
}
public void addMovie(CDMMovie p_Movie) {
m_Movies.add(p_Movie);
notifyCallbacks();
}
/**
* Registers a movie changed callback
*
* #param p_MovieChangedCallback the callback to register
*/
public void registerMovieChangedCallback(IDMMovieChangedCallback p_MovieChangedCallback) {
m_MovieChangedCallbacks.add(p_MovieChangedCallback);
}
/**
* Removes a movie changed callback
*
* #param p_MovieChangedCallback the callback to remove
*/
public void removeMovieChangedCallback(IDMMovieChangedCallback p_MovieChangedCallback) {
m_MovieChangedCallbacks.remove(p_MovieChangedCallback);
}
private void notifyCallbacks() {
for(IDMMovieChangedCallback l_MovieChangedCallback : m_MovieChangedCallbacks) {
l_MovieChangedCallback.onMoviesChanged();
}
}
}
And the implementing Class:
public class CDMBasicMovieFragment extends Fragment implements IDMMovieChangedCallback {
//...
#Override
public void onMoviesChanged() {
m_Adapter.notifyDataSetChanged();
}
}
I am getting some news data from my CMS,and want to display them in a RecyclerView.The problem is that I am getting a null pointer exception in the line where I using the LinearLayoutManager. Here is the logcat output.
Caused by: java.lang.NullPointerException
at testing.theo.manchesterunitedapp.newsandfeatures.FeaturesFragment.onCreateView(FeaturesFragment.java:65)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613)
at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:330)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:547)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1171)
at android.app.Activity.performStart(Activity.java:5241)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2157)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
at android.app.ActivityThread.access$800(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5001)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
The Fragment where I am doing the webservice part is quite simple. I use to callback methods. The onCreateView where I am initialising the ArrayList and the RecyclerView,and secondly the onActivityCreate where I am running the webservice.
public class FeaturesFragment extends Fragment {
public static final String TAG = "ManuApp";
private static final String IMAGE_URL = "xxxxxxxxxxxx/xxxx/features_images/" ;
private List<FeaturesObject> listItemsList;
private RecyclerView mRecyclerView;
private FeaturesAdapter adapter;
public FeaturesFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.features_row, container, false);
// Inflate the layout for this fragment
listItemsList = new ArrayList<>();
mRecyclerView = (RecyclerView)v.findViewById(R.id.features_recycler_view);
//mRecyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).color(Color.BLACK).build());
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(linearLayoutManager);
return v;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
updateFeaturesList();
}
public void updateFeaturesList() {
//declare the adapter and attach it to the recyclerview
adapter = new FeaturesAdapter(getActivity(), listItemsList);
mRecyclerView.setAdapter(adapter);
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(getActivity());
// Request a string response from the provided URL.
JsonArrayRequest jsObjRequest = new JsonArrayRequest(Request.Method.GET, Config.URL_FEATURES, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
//hidePD();
// Parse json data.
// Declare the json objects that we need and then for loop through the children array.
// Do the json parse in a try catch block to catch the exceptions
try {
for (int i = 0; i < response.length(); i++) {
JSONObject post = response.getJSONObject(i);
FeaturesObject item = new FeaturesObject();
item.setTitle(post.getString("title"));
item.setImage(IMAGE_URL + post.getString("features_image"));
item.setArticle(post.getString("article"));
listItemsList.add(item);
}
} catch (JSONException e) {
e.printStackTrace();
}
// Update list by notifying the adapter of changes
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
//hidePD();
}
});
jsObjRequest.setRetryPolicy(new RetryPolicy() {
#Override
public int getCurrentTimeout() {
return 50000;
}
#Override
public int getCurrentRetryCount() {
return 50000;
}
#Override
public void retry(VolleyError error) throws VolleyError {
}
});
queue.add(jsObjRequest);
}
}
This part of the code causes the problem.
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(linearLayoutManager);
This is strange,as I am using the same techiques to obtain data in another fragment of my app.
Any ideas?
Thanks.
Your RecyclerView is null. Are you sure you're looking for the correct id in the correct layout file? My guess is either you are inflating the incorrect layout file, or you're looking for the incorrect view id for the RecyclerView.
Probably this is not the case but... As a general rule all initialization that need instance of the activity must be in onActivityCreated() (or the next methods in the Fragment lifecycle). Inside onCreateView() getActivity() is not guaranteed to return non-null value. In some scenarios it returns null.
Seems like the id that you are trying to find it's not on features_row that's why you get NullPointerException on that line :
mRecyclerView = (RecyclerView)v.findViewById(R.id.features_recycler_view);
If you keep getting error you could try this :
final FragmentActivity c = getActivity();
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(c);
mRecyclerView.setLayoutManager(linearLayoutManager );
In my app I have a ViewPager with four fragments one of which contains a ListView which I dynamically add too at certain points using an update method that recreates the adapter. When the fragment is first loaded it displays all items perfectly but when I do operations later on, which add views to a list which is used to create the Fragment's ListView's adapter, the new items are not shown (or removed). Does anybody know why this occurs.
The Fragment with the ListView:
public static class FavoritesFragment extends Fragment
{
ListView list;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
update();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View lv = inflater.inflate(R.layout.fragment_favorites, null);
ListView list = (ListView) lv.findViewById(R.id.favorite_list);
SeparatedListAdapter mAdapter = new SeparatedListAdapter(getActivity(), favoriteList);
list.setAdapter(mAdapter);
return list;
}
public static FavoritesFragment newInstance(String text)
{
FavoritesFragment f = new FavoritesFragment();
Bundle b = new Bundle();
b.putString("msg", text);
f.setArguments(b);
return f;
}
}
The update method:
public static void update() {
favoriteList = new ArrayList<SeparatedListAdapter.Item>();
sections = new ArrayList<String>();
ListMultimap<String, JSONObject> listObjects = ArrayListMultimap.create();
try {
JSONObject obj = new JSONObject(loadJSONFromAsset(con));
JSONArray m_jArry = obj.getJSONArray("Locations");
for (int i = 0; i < m_jArry.length(); i++)
{
JSONObject jo_inside = m_jArry.getJSONObject(i);
if (favorites.contains(jo_inside.getString("Unique")))
{
listObjects.put(jo_inside.getString("Section"), jo_inside);
if (!sections.contains(jo_inside.getString("Section"))) sections.add(jo_inside.getString("Section"));
}
}
}
catch (JSONException e)
{
e.printStackTrace();
}
for (String s : sections)
{
favoriteList.add(new SeparatedListAdapter.SectionItem(s));
List<JSONObject> objectsInSection = listObjects.get(s);
for (JSONObject j : objectsInSection)
{
try {
favoriteList.add(new SeparatedListAdapter.EntryItem(j.getString("name");
}
catch (JSONException e)
{
}
}
}
}
When page is changed to Fragment with ListView:
View vc = mPager.findViewWithTag("favorites");
if (vc != null) {
ListView lv = (ListView) vc.findViewById(R.id.favorite_list);
update();
lv.setAdapter(new SeparatedListAdapter(MainActivity.this, favoriteList));
}
Sorry for the long post but any help would be really appreciated :)
have you tried calling this:
have mAdapter be an instance variable instead of instantiating it in the onCreateView
mAdapter.notifyDataSetChanged();
EDIT:::
what if you did something like this?
mAdapter.clear();
mAdapter.addAll(favoriteList);
I have an app with ViewPager and ViewPagerIndicator. I have two tabs made with TabPageIndicator. Each tab loads a listivew with data of Internet. When I run the app loads the data from tab 1 and 2, this causes very slow to show the view.
I want that when I started my app only load data tab 1 and when I move or click on tab 2 load the data for that tab.
Can you help me?
Thank you.
My code:
MainActivity
public class MainActivity extends FragmentActivity {
private static final String[] CONTENT = new String[] { "Releases", "Artists" };
private ListView listRls;
private List<Fragment> listaFragments;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
listaFragments = new ArrayList<Fragment>();
listaFragments.add(new FragmRls());
listaFragments.add(new FragmArt());
MyFragmentAdapter adapter = new MyFragmentAdapter(getSupportFragmentManager(),
listaFragments);
ViewPager pager = (ViewPager)findViewById(R.id.pager);
pager.setAdapter(adapter);
TabPageIndicator indicator = (TabPageIndicator)findViewById(R.id.indicator);
indicator.setViewPager(pager);
}
class MyFragmentAdapter extends FragmentStatePagerAdapter {
//Implementacion del fragmentStateADapter
private List<Fragment> fragments;
public MyFragmentAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
// TODO Auto-generated constructor stub
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
// TODO Auto-generated method stub
return fragments.get(position);
}
#Override
public CharSequence getPageTitle(int position) {
return CONTENT[position % CONTENT.length].toUpperCase();
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return fragments.size();
}
}//fin adapter
}//fin class
Code in one of the classes that extend from ListFragement, the other is identical.
public class FragmRls extends ListFragment{
JSONParser jParser = new JSONParser();
private static String url_all_post = "http://adeptlabel.com/listReleaseforTab.php";
private static String url_all_art = "http://adeptlabel.com/listArtists.php";
private static final String TAG_SUCCESS = "success";
private static final String TAG_posts = "wp_posts";
private static final String TAG_TITULO = "titulo";
private static final String TAG_IMAGEN = "imagen";
JSONArray posts = null;
private ArrayList <ElementosList> elementos = new ArrayList <ElementosList>();
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
return inflater.inflate(R.layout.fragmrls, null);
}//Fin On CreateView
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
elementos.clear();
loadDataJsonRls();
for(int i=0;i<ListViewConfig.getResim_list_txt().size();i++)
{
elementos.add(new ElementosList(ListViewConfig.getResim_list_txt().get(i),
ListViewConfig.getResim_list_img().get(i)));
}
ArrayAdapter<ElementosList>adaptador = new AdaptadorList(getActivity(),elementos);
setListAdapter(adaptador);
}
public void loadDataJsonRls()
{
List<NameValuePair> params = new ArrayList<NameValuePair>();
// getting JSON string from URL
JSONObject json = jParser.makeHttpRequest(url_all_post, "GET", params);
// Check your log cat for JSON reponse
Log.d("All releases: ", json.toString());
try {
// Checking for SUCCESS TAG
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
posts = json.getJSONArray(TAG_posts);
//Borramos los arrayList
ListViewConfig.deleteResim_list_img();
ListViewConfig.deleteResim_list_txt();
// looping through All post
for (int i = 0; i < posts.length(); i++) {
boolean repite = false;
JSONObject c = posts.getJSONObject(i);
// Storing each json item in variable
String titulo = c.getString(TAG_TITULO);
String imagen = c.getString(TAG_IMAGEN);
for(int j=0;j<ListViewConfig.getResim_list_txt().size();j++)
{
if(titulo.equals(ListViewConfig.getResim_list_txt().get(j)))
{
repite = true;
}
}
if(repite==false)
{
ListViewConfig.addImageUrls(imagen);
ListViewConfig.addTextUrls(titulo);
}
}
} else {
//Log.d("MainActivity.class", "No success Json");
}
} catch (JSONException e) {
e.printStackTrace();
}
}//fin cargarDatosJsonRls()
}//fin class
If you want to load data associated with second tab when user switch to that tab, try to move code that loads data from onCreate to a public method. Then set OnPageChangeListener and load data when onPageSelected is called.
Furthermore, make sure that you load data asynchronously, for example using AsyncTask.
You are making your network calls on the UI thread, this is why your UI is slow. You may want to use an AsyncTask, effectively moving your network activity to another thread. Its doInBackground method will handle the network things, and the onPostExecute method allows you to update your UI when the execution of the Task is finished. More details in the official documentation here.
Additionally, depending on your needs and time, you could either pre-load the data so the loading time when the user is presented with the screen is reduced, or show a ProgressBar while you are loading the data, then update the UI when loading is done.
The solution to my problem I found here:
(ViewPager, ListView, and AsyncTask, first page blank, all data in the second page
However, thanks for your attention Nartus and 2Dee.