Android - 如何从 FragmentActivity 访问片段
Android - How to access a Fragment from a FragmentActivity
当我尝试从我的主 activity 中访问一个片段时,我总是得到一个 NullPointerException
。不管我做什么。
问题是我使用 TabsPagerAdapter
和 ViewPager
并且我不知道如何获得膨胀的视图(片段的 onCreate()
方法 returns已查看)。
目标是访问片段内的元素并通过单个后台线程动态隐藏或显示它,这也应该对更多片段执行此操作。
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>
请帮帮我,我完全卡住了!
谢谢!
编辑:
testFunction() 中的第二行抛出 NullPointerException:
GridLayout gridlayout = (GridLayout) fragmentPage1.getRootView().findViewById(R.id.adBannerBasicLayout);
因为 getSupportFragmentManager()
总是 returns null:
FragmentPage1 fragmentPage1 = (FragmentPage1) getSupportFragmentManager().findFragmentById(R.layout.fragment_page1);
Logcat输出
java.lang.IllegalStateException: Could not execute method of the activity
at android.view.View.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.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.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)
您使用 getSupportFragmentManager() 获取片段。
请仔细检查您的 FragmentPage1 是否扩展了 android.support.v4.app.Fragment;
不是
android.Fragment;
使用import android.support.v4.app.Fragment
代替import android.app.Fragment
请将此添加到您的 gradle 依赖项中
compile 'com.android.support:support-v4:22.1.1'
编辑:请使用 findFragmentById(R.id.fragment_page1) 代替 R.layout
FragmentPage1 fragmentPage1 = (FragmentPage1) getSupportFragmentManager().findFragmentById(R.id.fragment_page1);
更新SDK和仓库后,又出现了新的问题。我不能再构建了,我不想在 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.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.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
您使用的是自动生成的 R 文件中的错误静态值!
而不是使用引用 XML 资源的 R.layout.fragment_page1 您应该使用 R.id.fragment_page1 这应该是您的 R.layout.activity_main XML 文件中片段的 ID /res/layout/activity_main.xml
- R.layout 引用 XML 布局文件
- R.id 引用单个 XML 节点(视图、片段等)
简而言之,更改:
FragmentPage1 fragmentPage1 = (FragmentPage1) getSupportFragmentManager().findFragmentById(R.layout.fragment_page1);
收件人:
FragmentPage1 fragmentPage1 = (FragmentPage1) getSupportFragmentManager().findFragmentById(R.id.fragment_page1);
并确保 /res/layout/activity_main.xml 中的片段 ID 设置为 R.id.fragment_page1 像这样:
<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" />
我还找到了另一个答案,这是我认为最满意的:)
忘了说还有一个class。这一切都来自于 developers.google.com ...
上某处可用的滑动视图的愚蠢示例代码
每次我尝试使用愚蠢的 getItem(int i) 方法通过我的 TabPagerAdapter class 访问 FragmentPages 时,我都会创建一个新的 Fragment() :-/ 非常烦人!
Class 来自错误 google 示例的 TabsPagerAdapter
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;
}
}
真是一派胡言^^我只是把它复制过来然后完全忘记了它的存在;)
将片段的实例化移至构造函数并保留它们以备后用。现在完美运行。
Class 优化后的TabsPagerAdapter
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;}
}
不再有多余的 FragmentPage1、Fragment2、FragmentPage3 classes,当然现在只有 FragmentPage 和 FragmentSettingsPage(扩展 FragmentPage 以覆盖 OnCreateView 方法),这会产生更清晰和更易理解的代码。
Class片段页面
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;
}
}
有什么想法可以进一步改进吗?
当我尝试从我的主 activity 中访问一个片段时,我总是得到一个 NullPointerException
。不管我做什么。
问题是我使用 TabsPagerAdapter
和 ViewPager
并且我不知道如何获得膨胀的视图(片段的 onCreate()
方法 returns已查看)。
目标是访问片段内的元素并通过单个后台线程动态隐藏或显示它,这也应该对更多片段执行此操作。
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>
请帮帮我,我完全卡住了!
谢谢!
编辑:
testFunction() 中的第二行抛出 NullPointerException:
GridLayout gridlayout = (GridLayout) fragmentPage1.getRootView().findViewById(R.id.adBannerBasicLayout);
因为 getSupportFragmentManager()
总是 returns null:
FragmentPage1 fragmentPage1 = (FragmentPage1) getSupportFragmentManager().findFragmentById(R.layout.fragment_page1);
Logcat输出
java.lang.IllegalStateException: Could not execute method of the activity
at android.view.View.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.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.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)
您使用 getSupportFragmentManager() 获取片段。 请仔细检查您的 FragmentPage1 是否扩展了 android.support.v4.app.Fragment; 不是 android.Fragment;
使用import android.support.v4.app.Fragment
代替import android.app.Fragment
请将此添加到您的 gradle 依赖项中
compile 'com.android.support:support-v4:22.1.1'
编辑:请使用 findFragmentById(R.id.fragment_page1) 代替 R.layout
FragmentPage1 fragmentPage1 = (FragmentPage1) getSupportFragmentManager().findFragmentById(R.id.fragment_page1);
更新SDK和仓库后,又出现了新的问题。我不能再构建了,我不想在 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.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.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
您使用的是自动生成的 R 文件中的错误静态值!
而不是使用引用 XML 资源的 R.layout.fragment_page1 您应该使用 R.id.fragment_page1 这应该是您的 R.layout.activity_main XML 文件中片段的 ID /res/layout/activity_main.xml
- R.layout 引用 XML 布局文件
- R.id 引用单个 XML 节点(视图、片段等)
简而言之,更改:
FragmentPage1 fragmentPage1 = (FragmentPage1) getSupportFragmentManager().findFragmentById(R.layout.fragment_page1);
收件人:
FragmentPage1 fragmentPage1 = (FragmentPage1) getSupportFragmentManager().findFragmentById(R.id.fragment_page1);
并确保 /res/layout/activity_main.xml 中的片段 ID 设置为 R.id.fragment_page1 像这样:
<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" />
我还找到了另一个答案,这是我认为最满意的:)
忘了说还有一个class。这一切都来自于 developers.google.com ...
上某处可用的滑动视图的愚蠢示例代码每次我尝试使用愚蠢的 getItem(int i) 方法通过我的 TabPagerAdapter class 访问 FragmentPages 时,我都会创建一个新的 Fragment() :-/ 非常烦人!
Class 来自错误 google 示例的 TabsPagerAdapter
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;
}
}
真是一派胡言^^我只是把它复制过来然后完全忘记了它的存在;)
将片段的实例化移至构造函数并保留它们以备后用。现在完美运行。
Class 优化后的TabsPagerAdapter
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;}
}
不再有多余的 FragmentPage1、Fragment2、FragmentPage3 classes,当然现在只有 FragmentPage 和 FragmentSettingsPage(扩展 FragmentPage 以覆盖 OnCreateView 方法),这会产生更清晰和更易理解的代码。
Class片段页面
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;
}
}
有什么想法可以进一步改进吗?