I always get a NullPointerException when I try to access a fragment from inside my main activity. No matter what I do.
The issue is that I use TabsPagerAdapter and ViewPager and I don't know how to get the inflated views (the fragment's onCreate() method returns the inflated view already).
The goal is to get access to an element inside the fragment and hide or show it dynamically by a single background thread which should also do this for more fragments.
MainActivity.java
public class MainActivity extends FragmentActivity implements
ActionBar.TabListener
{
/* swipe view */
private ViewPager viewPager;
private TabsPagerAdapter mAdapter;
private android.app.ActionBar actionBar;
// tab titles
private String[] tabs = { "Basic", "Advanced", "Settings"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* init swipe views */
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setAdapter(mAdapter);
actionBar = getActionBar();
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
/* addTab returns void, how to geht my fragements and their views???*/
for (String tabName : tabs)
actionBar.addTab(actionBar.newTab().setText(tabName).setTabListener(this));
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
#Override
public void onPageScrollStateChanged(int arg0) {}
});
}
public void testFunction()
{
FragmentPage1 fragmentPage1 = (FragmentPage1) getSupportFragmentManager().findFragmentById(R.layout.fragment_page1);
GridLayout gridlayout = (GridLayout) fragmentPage1.getRootView().findViewById(R.id.adBannerBasicLayout);
gridlayout.setVisibility(GridLayout.VISIBLE); /* THATS MY GOAL */
}
FragmentPage1.java
public class FragmentPage1 extends Fragment {
private View rootView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_page1, container, false);
/* HERE IT IS WORKING FINE,
but later I want to make it visible again
from code OUTSIDE FragmentPage1 ??? */
GridLayout gridlayout = (GridLayout) rootView.findViewById(R.id.adBannerBasicLayout);
gridlayout.setVisibility(GridLayout.GONE);
return rootView;
}
/* so I tried this, but also get always NullPointerException */
public View getRootView()
{
return rootView;
}
}
fragment_page1.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="#+id/settings_scroll_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#000000"
android:orientation="vertical"
android:rowCount="12"
android:columnCount="5"
>
<!-- Some Banner Ads I want to hide show -->
<!-- I want to access this from everywhere! -->
<GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="#+id/adBannerBasicLayout"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="fill"
android:rowCount="3"
android:columnCount="1"
android:layout_row="0"
android:layout_column="0"
android:layout_columnSpan="5">
<Space
android:layout_width="0dp"
android:layout_height="5dp"
android:layout_row="0"
android:layout_column="0"
/>
<com.google.android.gms.ads.AdView
android:id="#+id/adBannerBasic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="fill"
ads:adSize="BANNER"
ads:adUnitId="xxxxxxxxxxxxxxxxxxxxxxxxxx"
android:layout_row="1"
android:layout_column="0"
>
</com.google.android.gms.ads.AdView>
<Space
android:layout_width="0dp"
android:layout_height="5dp"
android:layout_row="2"
android:layout_column="0"
/>
</GridLayout>
<!-- more stuff... -->
</GridLayout>
</ScrollView>
Please help me out, I'm totally stuck!
THANKS!
EDIT:
The scond line in testFunction() throws the NullPointerException:
GridLayout gridlayout = (GridLayout) fragmentPage1.getRootView().findViewById(R.id.adBannerBasicLayout);
because getSupportFragmentManager() always returns null:
FragmentPage1 fragmentPage1 = (FragmentPage1) getSupportFragmentManager().findFragmentById(R.layout.fragment_page1);
Logcat Outoput
java.lang.IllegalStateException: Could not execute method of the activity
at android.view.View$1.onClick(View.java:3969)
at android.view.View.performClick(View.java:4633)
at android.view.View$PerformClick.run(View.java:19330)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
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:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at android.view.View$1.onClick(View.java:3964)
at android.view.View.performClick(View.java:4633)
at android.view.View$PerformClick.run(View.java:19330)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
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:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at org.tzapp.smote.MainActivity.testFuntion(MainActivity.java:393)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at android.view.View$1.onClick(View.java:3964)
at android.view.View.performClick(View.java:4633)
at android.view.View$PerformClick.run(View.java:19330)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
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:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
at dalvik.system.NativeStart.main(Native Method)
You are using the wrong static value from the auto generated R file!
Instead of using R.layout.fragment_page1 which references the XML resource you should use R.id.fragment_page1 which should be the id of the fragment in your R.layout.activity_main XML file at /res/layout/activity_main.xml
R.layout references XML layout files
R.id references individual XML nodes (Views, Fragments etc.)
So in short, change:
FragmentPage1 fragmentPage1 = (FragmentPage1) getSupportFragmentManager().findFragmentById(R.layout.fragment_page1);
To:
FragmentPage1 fragmentPage1 = (FragmentPage1) getSupportFragmentManager().findFragmentById(R.id.fragment_page1);
And make sure that your fragment id in /res/layout/activity_main.xml is set to R.id.fragment_page1 like so:
<fragment android:name="com.example.yourpackage.FragmentPage1"
android:id="#+id/fragment_page1"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
you use getSupportFragmentManager() to get fragment.
Please double check if your FragmentPage1 extends a android.support.v4.app.Fragment;
not a
android.Fragment;
After updating SDK and repository, there is new trouble. I cant build anymore and I dont want to compile on level 23 :(
Information:Gradle tasks [clean, :app:generateDebugSources, :app:generateDebugTestSources]
:app:clean
:app:preBuild
:app:preDebugBuild
:app:checkDebugManifest
:app:preReleaseBuild
:app:prepareComAndroidSupportAppcompatV72300Library
:app:prepareComAndroidSupportSupportV42300Library
:app:prepareComGoogleAndroidGmsPlayServicesAds750Library
:app:prepareComGoogleAndroidGmsPlayServicesAnalytics750Library
:app:prepareComGoogleAndroidGmsPlayServicesBase750Library
:app:prepareComInstabugLibraryInstabugcore161Library
:app:prepareComInstabugLibraryInstabugsupport161Library
:app:prepareDebugDependencies
:app:compileDebugAidl
:app:compileDebugRenderscript
:app:generateDebugBuildConfig
:app:generateDebugAssets UP-TO-DATE
:app:mergeDebugAssets
:app:generateDebugResValues UP-TO-DATE
:app:generateDebugResources
:app:mergeDebugResources
:app:processDebugManifest
:app:processDebugResources
C:\Users\Tom\AndroidStudioProjects\SSMote\app\build\intermediates\exploded-aar\com.android.support\appcompat-v7\23.0.0\res\values-v23\values-v23.xml
Error:(1) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Inverse'.
Error:(1) Error retrieving parent for item: No resource found that matches the given name 'android:Widget.Material.Button.Colored'.
Error:Execution failed for task ':app:processDebugResources'.
> com.android.ide.common.internal.LoggedErrorException: Failed to run command:
C:\Users\Tom\AppData\Local\Android\sdk\build-tools\21.1.2\aapt.exe package -f --no-crunch -I C:\Users\Tom\AppData\Local\Android\sdk\platforms\android-21\android.jar -M C:\Users\Tom\AndroidStudioProjects\SSMote\app\build\intermediates\manifests\full\debug\AndroidManifest.xml -S C:\Users\Tom\AndroidStudioProjects\SSMote\app\build\intermediates\res\debug -A C:\Users\Tom\AndroidStudioProjects\SSMote\app\build\intermediates\assets\debug -m -J C:\Users\Tom\AndroidStudioProjects\SSMote\app\build\generated\source\r\debug -F C:\Users\Tom\AndroidStudioProjects\SSMote\app\build\intermediates\res\resources-debug.ap_ --debug-mode --custom-package org.tzapp.smote -0 apk --output-text-symbols C:\Users\Tom\AndroidStudioProjects\SSMote\app\build\intermediates\symbols\debug
Error Code:
1
Output:
C:\Users\Tom\AndroidStudioProjects\SSMote\app\build\intermediates\res\debug\values-v23\values.xml:5: error: Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Inverse'.
C:\Users\Tom\AndroidStudioProjects\SSMote\app\build\intermediates\res\debug\values-v23\values.xml:20: error: Error retrieving parent for item: No resource found that matches the given name 'android:Widget.Material.Button.Colored'.
Information:BUILD FAILED
Information:Total time: 40.157 secs
Information:3 errors
Information:0 warnings
Also I found another answer, which is I think most satisfying :)
I forgot to mention that there is another class. It all comes from that stupid piece of example code for Swipe Views which is avaible somewhere on developers.google.com ...
Everytime I tried to access the FragmentPages via my TabPagerAdapter class using the stupid getItem(int i) method, I created a new Fragment() :-/ Very irritating!
Class TabsPagerAdapter from bad google example
public class TabsPagerAdapter extends FragmentPagerAdapter {
public TabsPagerAdapter(FragmentManager fm, MainActivity mainActivity){
super(fm);
}
// page index, fragment selector
#Override
public Fragment getItem(int index) {
switch (index)
{
case 0: return new FragmentPage1(); // bad practice
case 1: return new FragmentPage2(); // why should one do that?
case 2: return new FragmentPage3();
}
return null;
}
#Override
public int getCount() {
return 3;
}
}
What a piece of crap ^^ And I just copied it over and then totally forgot about it's existence ;)
Moved instanciation of fragments to constructor and keeped them for later use. Works perfectly now.
Class TabsPagerAdapter after optimization
public class TabsPagerAdapter extends FragmentPagerAdapter {
// hosted fragments
private FragmentPage fragmentPageBasic;
private FragmentPage fragmentPageAdvanced;
private FragmentPage fragmentPageSettings;
//constructor
public TabsPagerAdapter(FragmentManager fm, MainActivity mainActivity){
super(fm);
fragmentPageBasic = new FragmentPage();
fragmentPageBasic.setMainActivity(mainActivity);
fragmentPageBasic.setLayoutResource(R.layout.fragment_page1);
fragmentPageBasic.setAdBannerResource(R.id.adBannerBasic);
fragmentPageBasic.setAdBannerLayoutResource(R.id.adBannerBasicLayout);
fragmentPageAdvanced = new FragmentPage();
fragmentPageAdvanced.setMainActivity(mainActivity);
fragmentPageAdvanced.setLayoutResource(R.layout.fragment_page2);
fragmentPageAdvanced.setAdBannerResource(R.id.adBannerAdvanced);
fragmentPageAdvanced.setAdBannerLayoutResource(R.id.adBannerAdvancedLayout);
fragmentPageSettings = new FragmentSettingsPage();
fragmentPageSettings.setMainActivity(mainActivity);
fragmentPageSettings.setLayoutResource(R.layout.fragment_page3);
fragmentPageSettings.setAdBannerResource(R.id.adBannerSettings);
fragmentPageSettings.setAdBannerLayoutResource(R.id.adBannerSettingsLayout);
}
// page index, fragment selector
#Override
public Fragment getItem(int index) {
switch (index)
{
case 0: return fragmentPageBasic;
case 1: return fragmentPageAdvanced;
case 2: return fragmentPageSettings;
}
return null;
}
#Override
public int getCount() {
return 3;
}
// GETTERS
public FragmentPage getFragmentPageBasic() {return fragmentPageBasic;}
public FragmentPage getFragmentPageAdvanced() {return fragmentPageAdvanced;}
public FragmentPage getFragmentPageSettings() {return fragmentPageSettings;}
}
Instead of having redundant FragmentPage1, Fragment2, FragmentPage3 classes, of course now there is only FragmentPage and FragmentSettingsPage (extends FragmentPage to override OnCreateView method), which results in a much cleaner and more understandable code.
Class FragmentPage
public class FragmentPage extends Fragment {
protected MainActivity mainActivity;
// layout resource
protected int layoutResource;
// view
protected View rootView;
//Admob
protected AdView adBanner;
protected int adBannerResource;
protected int adBannerLayoutResource;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
onCreate(inflater, container);
return rootView;
}
// manage common onCreate things
protected void onCreate(LayoutInflater inflater, ViewGroup container)
{
rootView = inflater.inflate(layoutResource, container, false);
// admob banner
adBanner = (AdView) rootView.findViewById(adBannerResource);
adBanner.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {
}
#Override
public void onAdOpened() {
}
#Override
public void onAdClosed() {
newAdBannerRequest();
}
#Override
public void onAdFailedToLoad(int errorCode) {
newAdBannerRequest();
}
#Override
public void onAdLeftApplication() {
}
});
if(mainActivity.showAdBanners())
{
newAdBannerRequest();
showAdBanner();
}
else
hideAdBanner();
}
// ADMOB
public void newAdBannerRequest()
{
AdRequest request = new AdRequest.Builder()
.addTestDevice(AdRequest.DEVICE_ID_EMULATOR) // All emulators
.addTestDevice("XXXXXXXXXXXXXXXXXXXXXXXXXX") // My Galaxy Nexus test phone
.build();
adBanner.loadAd(request);
}
public void showAdBanner()
{
GridLayout adBannerLayout = (GridLayout) rootView.findViewById(adBannerLayoutResource);
if(adBannerLayout.getVisibility() == GridLayout.GONE)
adBannerLayout.setVisibility(GridLayout.VISIBLE);
}
public void hideAdBanner()
{
GridLayout adBannerLayout = (GridLayout) rootView.findViewById(adBannerLayoutResource);
if(adBannerLayout.getVisibility() == GridLayout.VISIBLE)
adBannerLayout.setVisibility(GridLayout.GONE);
}
// GETTERS
public AdView getAdBanner() { return adBanner;}
public View getRootView() { return rootView;}
// SETTERS
public void setMainActivity(MainActivity mainActivity) {this.mainActivity = mainActivity;}
public void setLayoutResource(int layoutResource){this.layoutResource = layoutResource;}
public void setAdBannerResource(int adBannerResource){this.adBannerResource = adBannerResource;}
public void setAdBannerLayoutResource(int adBannerLayoutResource){this.adBannerLayoutResource = adBannerLayoutResource;}
}
Class FragmentSettingsPage
public class FragmentSettingsPage extends FragmentPage {
// Preferences
public static final String PREFS_NAME = "Preferences";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(inflater, container);
SharedPreferences preferences = mainActivity.getSharedPreferences(PREFS_NAME, 0);
// do some other top secret stuff here ;)
return rootView;
}
}
Any ideas how to improve this further ?
Use import android.support.v4.app.Fragment instead import android.app.Fragment
Please add this in your gradle dependencies
compile 'com.android.support:support-v4:22.1.1'
Edit : please use findFragmentById(R.id.fragment_page1) instead R.layout
FragmentPage1 fragmentPage1 = (FragmentPage1) getSupportFragmentManager().findFragmentById(R.id.fragment_page1);
Related
i am using Maps API to create a simple android app and i get a wierd error i can't solve. It usually happens when i rotate my device. I'm using google services 8.4.0
4-23 15:39:47.503 9419-9419/com.licenta.vladut.mmap E/Parcel: Class not found when unmarshalling: android.support.v7.widget.Toolbar$SavedState
java.lang.ClassNotFoundException: android.support.v7.widget.Toolbar$SavedState
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:308)
at android.os.Parcel.readParcelableCreator(Parcel.java:2275)
at android.os.Parcel.readParcelable(Parcel.java:2239)
at android.os.Parcel.readValue(Parcel.java:2146)
at android.os.Parcel.readSparseArrayInternal(Parcel.java:2540)
at android.os.Parcel.readSparseArray(Parcel.java:1868)
at android.os.Parcel.readValue(Parcel.java:2203)
at android.os.Parcel.readArrayMapInternal(Parcel.java:2479)
at android.os.BaseBundle.unparcel(BaseBundle.java:221)
at android.os.Bundle.getBundle(Bundle.java:782)
at com.google.android.gms.maps.internal.ao.a(:com.google.android.gms.alldynamite:74)
at maps.ei.bu.a(Unknown Source)
at maps.ei.n.a(Unknown Source)
at com.google.android.gms.maps.internal.i$a.onTransact(:com.google.android.gms.alldynamite:107)
at android.os.Binder.transact(Binder.java:380)
at com.google.android.gms.maps.internal.IMapFragmentDelegate$zza$zza.onCreateView(Unknown Source)
at com.google.android.gms.maps.SupportMapFragment$zza.onCreateView(Unknown Source)
at com.google.android.gms.dynamic.zza$4.zzb(Unknown Source)
at com.google.android.gms.dynamic.zza.zza(Unknown Source)
at com.google.android.gms.dynamic.zza.onCreateView(Unknown Source)
at com.google.android.gms.maps.SupportMapFragment.onCreateView(Unknown Source)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1036)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1230)
at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2315)
at android.support.v4.app.FragmentController.onCreateView(FragmentController.java:120)
at android.support.v4.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:357)
at android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:31)
at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:80)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:733)
at android.view.LayoutInflater.inflate(LayoutInflater.java:482)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:276)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:136)
at com.licenta.vladut.mmap.MainActivity.onCreate(MainActivity.java:54)
at android.app.Activity.performCreate(Activity.java:6020)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2259)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2368)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3947)
at android.app.ActivityThread.access$900(ActivityThread.java:149)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1290)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.v7.widget.Toolbar$SavedState" on path: DexPathList[[zip file "/data/data/com.google.android.gms/app_chimera/m/00000000/DynamiteModules-prod.apk"],nativeLibraryDirectories=[/data/data/com.google.android.gms/app_chimera/m/00000000/n/armeabi-v7a, /vendor/lib, /system/lib]]
at dalvik.system.BaseDexClassLoader.f
04-23 15:39:47.503 9419-9419/com.licenta.vladut.mmap D/AndroidRuntime: Shutting down VM
04-23 15:39:47.505 9419-9419/com.licenta.vladut.mmap E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.licenta.vladut.mmap, PID: 9419
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.licenta.vladut.mmap/com.licenta.vladut.mmap.MainActivity}: android.view.InflateException: Binary XML file line #2: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2306)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2368)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3947)
at android.app.ActivityThread.access$900(ActivityThread.java:149)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1290)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
Caused by: android.view.InflateException: Binary XML file line #2: Error inflating class fragment
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:763)
at android.view.LayoutInflater.inflate(LayoutInflater.java:482)
at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:276)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:136)
at com.licenta.vladut.mmap.MainActivity.onCreate(MainActivity.java:54)
at android.app.Activity.performCreate(Activity.java:6020)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2259)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2368)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3947)
at android.app.ActivityThread.access$900(ActivityThread.java:149)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1290)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
Caused by: android.os.BadParcelableException: ClassNotFoundException when unmarshalling: android.support.v7.widget.Toolbar$SavedState
at android.os.Parcel.readParcelableCreator(Parcel.java:2289)
at android.os.Parcel.readParcelable(Parcel.java:2239)
at android.os.Parcel.readValue(Parcel.java:2146)
at android.os.Parcel.readSparseArrayInternal(Parcel.java:2540)
at android.os.Parcel.readSparseArray(Parcel.java:1868)
at android.os.Parcel.readValue(Parcel.java:2203)
at android.os.Parcel.readArrayMapInternal(Parcel.java:2479)
at android.os.BaseBundle.unparcel(BaseBundle.java:221)
at android.os.Bundle.getBundle(Bundle.java:782)
at com.google.android.gms.maps.internal.ao.a(:com.google.android.gms.alldynamite:74)
at maps.ei.bu.a(Unknown Source)
at maps.ei.n.a(Unknown Source)
at com.google.android.gms.maps.internal.i$a.onTransact(:com.google.android.gms.alldynamite:107)
at android.os.Binder.transact(Binder.java:380)
at com.google.android.gms.maps.internal.IMapFragmentDelegate$zza$zza.onCreateView(Unknown Source)
at com.google.android.gms.maps.SupportMapFragment$zza.onCreateView(Unknown Source)
at com.google.android.gms.dynamic.zza$4.zzb(Unknown Source)
at com.google.android.gms.dynamic.zza.zza(Unknown Source)
at com.google.android.gms.dynamic.zza.onCreateView(Unknown Source)
at com.google.android.gms.maps.SupportMapFragment.onCreateView(Unknown Source)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1036)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1230)
at android.support.v4.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2315)
at android.support.v4.app.FragmentController.onCreateView(FragmentController.java:120)
at android.support.v4.app.FragmentActivity.dispatchFragmentsOnCreateView(FragmentActivity.java:357)
at android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:31)
at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:80)
at android.view.LayoutInf
My MainActivity.java is
package com.licenta.vladut.mmap;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
public class MainActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener, OnMapReadyCallback {
GoogleMap mMap;
private static final double BM_LAT = 47.6595076, BM_LNG = 23.5631243;
private Toolbar toolbar;
private GoogleApiClient mGoogleApiClient;
private static final String TAG = "SignInActivity";
private static final int ERROR_DIALOG_REQUEST = 9001;
private static final int RC_SIGN_IN = 9002;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.addApi(AppIndex.API).build();
if (checkPlayServices()) {
setContentView(R.layout.activity_map);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
(MainActivity.this).setSupportActionBar(toolbar);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
} else {
setContentView(R.layout.activity_main);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.sign_out) {
signOut();
return true;
}
return super.onOptionsItemSelected(item);
}
private void signOut() {
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
toSignIn();
}
});
}
private void toSignIn() {
Intent i = new Intent(this, SignInActivity.class);
startActivity(i);
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// An unresolvable error has occurred and Google APIs (including Sign-In) will not
// be available.
Log.d(TAG, getString(R.string.onConnectionFailed) + connectionResult);
}
private boolean checkPlayServices() {
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
int result = googleAPI.isGooglePlayServicesAvailable(this);
if (result != ConnectionResult.SUCCESS) {
if (googleAPI.isUserResolvableError(result)) {
googleAPI.getErrorDialog(this, result,
ERROR_DIALOG_REQUEST).show();
} else {
Toast.makeText(this, "Nu se poate conecta la Google Play Services!", Toast.LENGTH_SHORT).show();
}
return false;
}
return true;
}
#Override
public void onMapReady(final GoogleMap map) {
this.mMap = map;
gotoLocation(BM_LAT,BM_LNG,18);
}
private void gotoLocation(double lat, double lng, float zoom){
LatLng latLng = new LatLng(lat, lng);
CameraUpdate update = CameraUpdateFactory.newLatLngZoom(latLng,zoom);
mMap.moveCamera(update);
}
}
Activity_main.xml is
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="match_parent"
tools:context="com.licenta.vladut.mmap.MainActivity">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar"
/>
</RelativeLayout>
activity_map.xml is
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar"
/>
</fragment>
and finally, toolbar.xml is
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
android:background="?attr/colorPrimary"
android:id="#+id/toolbar"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:minHeight="?attr/actionBarSize"
android:layout_width="match_parent"
android:layout_alignParentStart="true"
android:elevation="4dp"
app:popupTheme="#style/AppTheme.PopupOverlay"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
</android.support.v7.widget.Toolbar>
I didn't like provided solutions as it imposed on my layouts and architecture.
Here's what I did to make it work. If you look at your stacktrace the ClassNotFoundException is coming from the line on GoogleMaps. So if we just fix that, the issue is gone.
GoogleMaps pukes/throw an error when the savedInstanceState has other items in it besides it's own. The solution is to just give GoogleMaps it's own dedicated bundle.
// class property
private static final String KEY_MAP_SAVED_STATE = "mapState";
// class methods
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mapView = findMapView(); // make your own method here
Bundle mapState = (savedInstanceState != null)
? savedInstanceState.getBundle(KEY_MAP_SAVED_STATE): null;
mapView.onCreate(mapState);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Bundle mapState = new Bundle();
mapView.onSaveInstanceState(mapState);
outState.putBundle(KEY_MAP_SAVED_STATE, mapState);
}
One thing to note is I'm not using the SupportMapFragment. I'm using a MapView directly. You may have to extend the SupportMapFragment so you can catch the hook methods and provide a blank/clean bundle
Upon rotation, your SupportMapFragment gets destroyed and recreated. Before it's destroyed, it writes its current state to a Parcel, to be used in restoring its state when recreated. The Fragment's saved state will include the state of its child Views, and since you've nested a Toolbar within it, it attempts to save and restore that, as well. The Toolbar class does not have an inner class SavedState necessary for that, so this process fails when trying to restore the Toolbar instance from the Parcel.
The solution is to not nest the Toolbar - or any other View, for that matter - within the <fragment> element. Instead, pull the <include> out of the <fragment>, and put them both in another ViewGroup; for example, a vertical LinearLayout, or a RelativeLayout.
Changing activity_map.xml to this worked, thanks again Mike.
<?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">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" />
<fragment xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent">
</fragment>
</RelativeLayout>
I had a similar problem with my custom view and found this solution.
I noticed that this crash occurred when I extended RecyclerView or AppCompatSpinner and needed to save the state. The crash will probably happen for other views as well.
Basically the crash is caused by a bug in AbsSavedState as mentioned here.
And the crash only occurs when the constructor of the SavedState is called without a class loader. It seemed like this was an old issue however I started getting crash reports for Android 9 and 10.
So the fix was to change:
public SavedState(Parcel source) {
super(source);
//...
}
to:
public SavedState(Parcel source) {
super(source, LinearLayoutManager.class.getClassLoader());
//...
}
Edit
I was on the right track, but then I was looking at some Android code and found out that there was actually a constructor missing that caused the crash. So I had the following constructor for the SavedState:
SavedState(Parcel in)
{
super(in);
//...
}
And I needed to add the following:
#RequiresApi(Build.VERSION_CODES.N)
SavedState(Parcel in, ClassLoader loader)
{
super(in, loader);
//...
}
And then I needed to change the creator:
public static final Creator<SavedState> CREATOR = new ClassLoaderCreator<SavedState>()
{
#Override
public SavedState createFromParcel(Parcel source, ClassLoader loader)
{
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? new SavedState(source, loader) : new SavedState(source);
}
#Override
public SavedState createFromParcel(Parcel source)
{
return createFromParcel(source, null);
}
public SavedState[] newArray(int size)
{
return new SavedState[size];
}
};
I have created a dialog class that i would like to use in several other classes and depending in what class they should display different info. I have no problem displaying the dialog itself with working button and an already set text from the xml. But when i try to set my own text with setText the app crashes and give me java.lang.NullPointerException. What can be the problem ?
Here is my custom dialog class
public class CustomDialogInfoClass extends Dialog implements View.OnClickListener {
Button ok;
TextView myTextView;
Typeface myFont;
public CustomDialogInfoClass(Context context) {
super(context);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.custom_dialog_not_demo);
CustomDialogInfoClass c = new CustomDialogInfoClass(getContext());
ok = (Button)findViewById(R.id.btnOk);
myTextView = (TextView) c.findViewById(R.id.textViewDialog);
ok.setOnClickListener(this);
myFont = Typeface.createFromAsset(getContext().getAssets(), "fonts/font.ttf");
ok.setTypeface(myFont);
myTextView.setTypeface(myFont);
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btnOk:
dismiss();
break;
default:
}
dismiss();
}
}
And here is my main where I try to call it;
public class MainActivity extends ActionBarActivity {
TextView myTextview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CustomDialogInfoClass dialogInfo = new CustomDialogInfoClass(this);
myTextview = (TextView) findViewById(R.id.textViewDialog);
myTextview.setText("Lorem ipsum dolor sit amet"); <----Null.pointer error
dialogInfo.show();
}
xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:orientation="vertical"
android:background="#drawable/diabox"
android:weightSum="1">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="#+id/textViewDialog"
android:layout_margin="15dp"
android:textColor="#android:color/white"
android:text="Test text" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ok"
android:id="#+id/btnOk"
android:layout_gravity="center_horizontal" />
and logcat if that helps?
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.name.appname/com.example.name.appname.MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2221)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2280)
at android.app.ActivityThread.access$800(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1202)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5064)
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:797)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:613)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.example.name.appnamne.MainActivity.onCreate(MainActivity.java:35)
at android.app.Activity.performCreate(Activity.java:6084)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2178)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2280)
at android.app.ActivityThread.access$800(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1202)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5064)
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:797)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:613)
at dalvik.system.NativeStart.main(Native Method)
you shouldn't access your text view from activity
in your dialog you have this constructor
public CustomDialogInfoClass(Context context) {
super(context);
}
so make this one too:
public CustomDialogInfoClass(Context context,String text) {
CustomDialogInfoClass(context);
this.text = text;
}
and make a String field in your dialog class
String text;
and setup your TextView in the dialog
myTextView = (TextView) c.findViewById(R.id.textViewDialog);
myTextView.setText(text);
and in your activity pass your text here:
CustomDialogInfoClass c = new CustomDialogInfoClass(getContext(), "MY TEXT");
You need to set the value of the TextView from inside your dialog during onCreate method.
To pass parameters to the dialog the proper way would be to have a static method in you Dialog class that return a new instance of the Object.
This method can accept paramaters and put them in a Bundle. Now you can set this bundle as argument to the created Dialog
public static YourDialog getInstance(String par1, int par2) {
YourDialog dialog = new YourDialog()
Bundle bundle = new Bundle();
bundle.putString(TAG, par1);
bundle.putInt(TAG2, par2);
dialog.setArguments(bundle);
return dialog;
}
At this point in the OnCreate method of your dialog you can get the Bundle using getArguments() using the tag you provided before and set your TextView
Once you have done in your MainActivity get an Instance of the dialog and call show() to show it
Hope it helps
This is my first time working with the recyclerview and I am getting some errors about android:onClick="addItem" here is what I get when I try to add a line of text to my recyclerview. I usually use my phone to test my apps.
java.lang.IllegalStateException: Could not execute method of the activity
at android.view.View$1.onClick(View.java:4012)
at android.view.View.performClick(View.java:4761)
at android.view.View$PerformClick.run(View.java:19767)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5312)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at android.view.View$1.onClick(View.java:4007)
at android.view.View.performClick(View.java:4761)
at android.view.View$PerformClick.run(View.java:19767)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5312)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.text.Editable android.widget.EditText.getText()' on a null object reference
at com.sapps.app.testapp2.MainActivity.addItem(MainActivity.java:53)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at android.view.View$1.onClick(View.java:4007)
at android.view.View.performClick(View.java:4761)
at android.view.View$PerformClick.run(View.java:19767)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5312)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:901)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:696)
Here is my code where I think is the error, but I don't know exactly:
public class MainActivity extends ActionBarActivity {
private EditText mText;
private RecyclerView.LayoutManager mLayoutManager;
private RecyclerView recyclerView;
private Button btn;
private CustomRecyclerAdapter mAdapter;
private List<Data> mData = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initializing views.
mText = (EditText) findViewById(R.id.textEt);
recyclerView = (RecyclerView) findViewById(R.id.recycler);
// If the size of views will not change as the data changes.
recyclerView.setHasFixedSize(true);
// Setting the LayoutManager.
mLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(mLayoutManager);
// Setting the adapter.
CustomRecyclerAdapter mAdapter = new CustomRecyclerAdapter();
recyclerView.setAdapter(mAdapter);
}
// Called when add button is clicked.
public void addItem(View v) {
if(mText!=null) {
Data dataToAdd = new Data(mText.getText().toString()); mData.add(dataToAdd);
}
}
}
And here is my recyclerview adapter to know for sure:
public class CustomRecyclerAdapter extends RecyclerView.Adapter<RecyclerViewHolder> {
CustomRecyclerAdapter mAdapter;
private List<Data> mData = Collections.emptyList();
public CustomRecyclerAdapter() {
// Pass context or other static stuff that will be needed.
}
public void updateList(List<Data> data) {
mData = data;
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return mData.size();
}
#Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup viewGroup, int position) {
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
View itemView = inflater.inflate(R.layout.list_item, viewGroup, false);
return new RecyclerViewHolder(itemView);
}
#Override
public void onBindViewHolder(RecyclerViewHolder viewHolder, int position) {
viewHolder.title.setText(mData.get(position).text);
}
public void addItemInRec(int position, Data data) {
mData.add(data);
notifyItemInserted(position);
}
public void removeItem(int position) {
mData.remove(position);
notifyItemRemoved(position);
}
}
My MainActivity xml file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/textEt"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="Text"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Add"
android:onClick="addItem"/>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"/>
</LinearLayout>
Maybe it is my ViewHolder:
public class RecyclerViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public RecyclerViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.title);
}
}
Or Data.java class:
public class Data {
public String text;
public Data(String text) {
this.text = text;
}
}
The key is in your error message:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.text.Editable android.widget.EditText.getText()' on a null object reference
at com.sapps.app.testapp2.MainActivity.addItem(MainActivity.java:53)
A good tip for learning from your error output is to look at each "Caused by" statement, and scan through the log until you find one of your own files referenced. Then that part of the error log will even tell you what line your code was failing on ( in this case it is line 53 on MainActivity.java).
A Null Pointer Exception in Java is when you attempt to call a method on some object 'A', but that object 'A' is currently null.
So this error message means:
"On line 53 of MainActivity.java, you tried to call a method on some object which doesn't exist yet, so I crashed."
The method that is failing is EditText mText = (EditText) findViewById(R.id.textEt);
Usually this type of failure means that you aren't finding the right ID from your layout. Double check that textEt is the correct ID for this layout element.
EDIT:
Still not sure why your views aren't getting populated, but I did notice an error with your adapter. You are redefining mAdapter, so you have 2 copies, one in local scope and one as a member to MainActivity. This will definitely mess things up.
Right here:
// Setting the adapter.
CustomRecyclerAdapter mAdapter = new CustomRecyclerAdapter();
recyclerView.setAdapter(mAdapter)
You are redefining mAdapter locally. Do this instead:
// Setting the adapter.
mAdapter = new CustomRecyclerAdapter();
recyclerView.setAdapter(mAdapter)
You are getting a null pointer on the getText() call
It means the following line:
EditText mText = (EditText) findViewById(R.id.textEt);
returns null, solution is to check and correct the layout so that textEt is on it.
Edit:
If you are sure that it's in the layout remove EditText declaration.
Declare as private EditText mText; on the class scope
setContentView(R.layout.name_of_layout_here);
mText = (EditText) findViewById(R.id.textEt);
The view in addItem(View v) is referring to the button only.
The EditText object that you want is not in the button, it is in the button's parent view.
If you try to access the object from the button view it will be null, because the button does not have it.
Instead you need to access the object from the button's parent view.
// Solution:
public void addItem(View v) {
View parentView = (View) v.getParent();
EditText mText = (EditText) parentView.findViewById(R.id.textEt);
Log.d("LOG", mText.getText().toString()));
}
I know that technically this does not solve the code in the question. But the code in the question has been changed from what produced the error so this would solve the original buggy code that actually produced the question.
I am guessing that the original buggy code looked like this:
// My guess this was the original buggy code
// MainActivity.java
public void addItem(View v) {
EditText mText = (EditText) v.findViewById(R.id.textEt);
Data dataToAdd = new Data(mText.getText().toString());
mData.add(dataToAdd);
}
// MainActivity.xml
<LinearLayout>
<EditText
android:id="#+id/textEt"
/>
<Button
android:text="Add"
android:onClick="addItem"/>
</LinearLayout>
Change public void addItemInRec to public void addItem. There is no method for onClick in mainActivity.
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 8 years ago.
I am working on a project which has many activities which uses recycler view in the exact way,just the data and onClickListener changes,
I have the following abstract class for creating different activities with different onClickListener
public abstract class AbstractActivity extends ActionBarActivity implements View.OnClickListener{
private final String[] data;
RecyclerView.LayoutManager layoutManager;
RecyclerView.Adapter adapter;
List<String> list;
Toolbar toolbar;
String title;
int id;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recycler);
Toolbar toolbar=(Toolbar)this.findViewById(R.id.toolbar);
toolbar.setLogo(R.drawable.ic_launcher);
toolbar.setTitle(title);
RecyclerView recyclerView=(RecyclerView)this.findViewById(R.id.recycler_view);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.addItemDecoration(new DividerItemDecoration(this, null));
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager=new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
list.add("Hello");
adapter=new CardAdapter(list,id,this);
recyclerView.setAdapter(adapter);
}
public AbstractActivity(String title,String[] data,int id){
this.title=title;
this.data=data;
this.id=id;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_abstract, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public abstract void onClick(View v);
}
}
The recycler layout file is
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".Syllabus">
<android.support.v7.widget.Toolbar android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="#dimen/abc_action_bar_default_height_material"
android:id="#+id/toolbar"
android:background="#03a9f4"
>
</android.support.v7.widget.Toolbar>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Now when i extend some class to create activity using the abstract class i get nullPointerException.The extend class is
public class Batch extends AbstractActivity {
public Batch(){
super("Hello",new String[]{"B.E Syllabus","B.Arch Syllabus","MBA Syllabus","MCA Syllabus","M.Tech Syllabus"},R.layout.main_page);
}
#Override
public void onClick(View v) {
}
}
logcat entry is
02-14 17:07:03.233 2807-2807/android.anoop.com.vtustudent E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{android.anoop.com.vtustudent/android.anoop.com.vtustudent.Batch}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2070)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2095)
at android.app.ActivityThread.access$600(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1201)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4849)
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:795)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at android.anoop.com.vtustudent.AbstractActivity.onCreate(AbstractActivity.java:37)
at android.app.Activity.performCreate(Activity.java:5236)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1082)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2034)
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2095)
at android.app.ActivityThread.access$600(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1201)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4849)
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:795)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
at dalvik.system.NativeStart.main(Native Method)
The toolbar in the recycler file is expanding fine and app runs perfectly if i remove the recyclerView from the layout file.Also if i use the same resource file in some activity directlyit works fine.I am getting the error only when i am using layout resource file from the abstract class.
Why is this happening and how to correct this.Also is the way of abstract class the right way or is there some other way for creating same kind of activities. I am new to android programming and any help will be appreciated.Thank you
list is never initialized. So list.add("Hello"); will throw a NPE.
Simply Change: List<String> list; to List<String> list = new ArrayList<String>();
I am trying to implement pageviewer in my app using this tutorial. But my app force closes. It shows android.view.InflateException: Binary XML file line #2: Error inflating class com.example.viewpager.ScrollView. Where I am going wrong? I am a beginner in android so please guide me. I thought I might have imported wrong libs as my app is supporting API 10. So I searched other answers but of no use. Here is my code:
MainActvity.java
package com.example.viewpager;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
public class MainActivity extends FragmentActivity {
/**
* The number of pages (wizard steps) to show in this demo.
*/
private static final int NUM_PAGES = 5;
/**
* The pager widget, which handles animation and allows swiping horizontally to access previous
* and next wizard steps.
*/
private ViewPager mPager;
/**
* The pager adapter, which provides the pages to the view pager widget.
*/
private PagerAdapter mPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Instantiate a ViewPager and a PagerAdapter.
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
}
#Override
public void onBackPressed() {
if (mPager.getCurrentItem() == 0) {
// If the user is currently looking at the first step, allow the system to handle the
// Back button. This calls finish() on this activity and pops the back stack.
super.onBackPressed();
} else {
// Otherwise, select the previous step.
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
}
}
/**
* A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
* sequence.
*/
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(android.support.v4.app.FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return new ScreenSlidePageFragment();
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
}
ScreenSlidePagerFragment.java
package com.example.viewpager;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class ScreenSlidePageFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_screen_slide_page, container, false);
return rootView;
}
}
actvity_main.xml
<?xml version="1.0" encoding="utf-8"?><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" />
fragment_slide_screen_page.xml
<?xml version="1.0" encoding="utf-8"?>
<com.example.viewpager.ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView style="?android:textAppearanceMedium"
android:padding="16dp"
android:lineSpacingMultiplier="1.2"
android:textColor="#000000"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Page 1" />
</com.example.viewpager.ScrollView>
Log cat:
android.view.InflateException: Binary XML file line #2: Error inflating class com.example.viewpager.ScrollView
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:581)
at android.view.LayoutInflater.inflate(LayoutInflater.java:386)
at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
at com.example.viewpager.ScreenSlidePageFragment.onCreateView(ScreenSlidePageFragment.java:14)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1478)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:927)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460)
at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:472)
at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:163)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1068)
at android.support.v4.view.ViewPager.populate(ViewPager.java:914)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1436)
at android.view.View.measure(View.java:8313)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
at android.view.View.measure(View.java:8313)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:531)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:309)
at android.view.View.measure(View.java:8313)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3138)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:250)
at android.view.View.measure(View.java:8313)
at android.view.ViewRoot.performTraversals(ViewRoot.java:845)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1865)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassNotFoundException: com.example.viewpager.ScrollView in loader dalvik.system.PathClassLoader[/data/app/com.example.viewpager-2.apk]
at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:240)
at java.lang.ClassLoader.loadClass(ClassLoader.java:551)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at android.view.LayoutInflater.createView(LayoutInflater.java:471)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:570)
... 33 more
change adapter to:
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
int layouts[];
public ScreenSlidePagerAdapter(android.support.v4.app.FragmentManager fm) {
super(fm);
layouts=new int[]{R.layout.fragment_slide_screen_page1,R.layout.fragment_slide_screen_page2,R.layout.fragment_slide_screen_page3,R.layout.fragment_slide_screen_page4,R.layout.fragment_slide_screen_page5};
}
#Override
public Fragment getItem(int position) {
ScreenSlidePageFragment fragment=new ScreenSlidePageFragment();
fragment.setContent(layouts[position]);
return fragment;
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
and in fragment:
public class ScreenSlidePageFragment extends Fragment {
int layout;
public void setContent(int layout){
this.layout=layout;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(layout, container, false);
return rootView;
}
}
Although not sure what change you want in each fragment but the above will require you to create 5 layout xmls that you can set every time you create a new Fragment.
Even I encountered crash.
This is because I was calling mAdapter.notifyDataSetChanged(); inside
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
Later I shifted the method to
#Override
public void onPageSelected(int arg0) {
mAdapter.notifyDataSetChanged();
}
So that did the trick