使用 ViewPager 从父 Activity 调用片段的方法
Call a Fragment's method from parent Activity using a ViewPager
我有一些来自 Slidenerd 的 Scrolltab 视频系列的示例代码,它运行得非常好。但是,我无法在父 activity 的片段内调用方法。例如,我在片段 A 中包含了一个名为 doSomething() 的方法。我想从 MainActivity 的 onResume() 回调中调用它。
编辑:
使用 "accepted answer" 适用于此应用程序,但不适用于我正在处理的实际应用程序,因为空指针异常。
错误日志
06-25 13:02:19.308 3862-3862/com.felhr.agweigh D/AndroidRuntime﹕ Shutting down VM
06-25 13:02:19.308 3862-3862/com.felhr.agweigh W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x416ecda0)
06-25 13:02:19.308 3862-3862/com.felhr.agweigh E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.felhr.agweigh, PID: 3862
java.lang.RuntimeException: Error receiving broadcast Intent { act=com.felhr.usbservice.USB_PERMISSION_GRANTED flg=0x10 } in com.felhr.agweigh.MainActivity@41da2c10
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:782)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5479)
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:1283)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.felhr.agweigh.FragmentPlotCSV.createSpinner(FragmentPlotCSV.java:102)
at com.felhr.agweigh.MainActivity.onReceive(MainActivity.java:894)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:772)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5479)
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:1283)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
at dalvik.system.NativeStart.main(Native Method)
清单
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.felhr.agweigh" >
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.usb.host"
android:required="true" />
<application
android:logo="@drawable/rinstrumlogo"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/RinstrumActionBarTheme" >
<activity
android:name="com.felhr.agweigh.MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.felhr.agweigh.UsbService"
android:enabled="true" >
</service>
</application>
</manifest>
主要活动
public class MainActivity extends FragmentActivity {
ViewPager viewPager = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager)findViewById(R.id.pager);
FragmentManager fragmentManager = getSupportFragmentManager();
viewPager.setAdapter(new MyAdapter(fragmentManager));
}
@Override
protected void onResume() {
super.onResume();
}
}
我的适配器
class MyAdapter extends FragmentPagerAdapter
{
public MyAdapter(FragmentManager fm)
{
super(fm);
}
@Override
public Fragment getItem(int i) {
Fragment fragment = null;
Log.d("SWIPE","get Item is called"+i);
if (i==0)
{
fragment=new FragmentA();
}
if (i==1)
{
fragment=new FragmentB();
}
if (i==2)
{
fragment=new FragmentC();
}
return fragment;
}
@Override
public int getCount() {
Log.d("SWIPE","get count is called");
return 3;
}
// talks to title to give the page
@Override
public CharSequence getPageTitle(int position) {
if (position == 0) {
return "Tab 1";
}
if (position == 1) {
return "Tab 2";
}
if (position == 2) {
return "Tab 3";
}
return null;
}
}
片段A
/**
* Created by Luke on 20/04/2015.
*/
public class FragmentA extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_a, container, false);
}
public void doSomething(){
// call this method from main activity
}
}
片段B
/**
* Created by Luke on 20/04/2015.
*/
public class FragmentB extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_a, container, false);
}
}
片段C
/**
* Created by Luke on 20/04/2015.
*/
public class FragmentC extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_a, container, false);
}
}
你可以这样做-
@Override
protected void onResume() {
super.onResume();
FragmentA _fragA = new FragmentA();
_fragA.doSomething();
}
您可以使用以下元素在清单文件中注册接收器:
<receiver android:name="MyReceiver" >
<intent-filter>
<action android:name="com.example.Broadcast" >
</action>
</intent-filter>
</receiver>
嵌套元素用于指定接收者应对的事件。
仅供参考,您的问题并非特定于使用 ViewPager。
根据设计,activity 除了 FragmentA 是一个 Fragment 之外对它一无所知,因此它不知道它包含 doSomething() 方法。快速而肮脏的方法是从适配器获取片段并在知道它是 FragmentA 时将其转换为 FragmentA。我说这是一种 "quick and dirty" 方式,因为你希望在 activity 和片段之间保持分离——即您的 activity 不需要了解您的 FragmentA 实现,只需要了解 Fragment。
当您构建更复杂的应用程序时,您需要研究使用事件总线以一种很好的解耦方式在片段和活动之间发送消息。以下是一些流行的 android 事件总线:
http://square.github.io/otto/
https://github.com/greenrobot/EventBus
我有一些来自 Slidenerd 的 Scrolltab 视频系列的示例代码,它运行得非常好。但是,我无法在父 activity 的片段内调用方法。例如,我在片段 A 中包含了一个名为 doSomething() 的方法。我想从 MainActivity 的 onResume() 回调中调用它。
编辑: 使用 "accepted answer" 适用于此应用程序,但不适用于我正在处理的实际应用程序,因为空指针异常。
错误日志
06-25 13:02:19.308 3862-3862/com.felhr.agweigh D/AndroidRuntime﹕ Shutting down VM
06-25 13:02:19.308 3862-3862/com.felhr.agweigh W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x416ecda0)
06-25 13:02:19.308 3862-3862/com.felhr.agweigh E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.felhr.agweigh, PID: 3862
java.lang.RuntimeException: Error receiving broadcast Intent { act=com.felhr.usbservice.USB_PERMISSION_GRANTED flg=0x10 } in com.felhr.agweigh.MainActivity@41da2c10
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:782)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5479)
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:1283)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.felhr.agweigh.FragmentPlotCSV.createSpinner(FragmentPlotCSV.java:102)
at com.felhr.agweigh.MainActivity.onReceive(MainActivity.java:894)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:772)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5479)
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:1283)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
at dalvik.system.NativeStart.main(Native Method)
清单
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.felhr.agweigh" >
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.usb.host"
android:required="true" />
<application
android:logo="@drawable/rinstrumlogo"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/RinstrumActionBarTheme" >
<activity
android:name="com.felhr.agweigh.MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.felhr.agweigh.UsbService"
android:enabled="true" >
</service>
</application>
</manifest>
主要活动
public class MainActivity extends FragmentActivity {
ViewPager viewPager = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager)findViewById(R.id.pager);
FragmentManager fragmentManager = getSupportFragmentManager();
viewPager.setAdapter(new MyAdapter(fragmentManager));
}
@Override
protected void onResume() {
super.onResume();
}
}
我的适配器
class MyAdapter extends FragmentPagerAdapter
{
public MyAdapter(FragmentManager fm)
{
super(fm);
}
@Override
public Fragment getItem(int i) {
Fragment fragment = null;
Log.d("SWIPE","get Item is called"+i);
if (i==0)
{
fragment=new FragmentA();
}
if (i==1)
{
fragment=new FragmentB();
}
if (i==2)
{
fragment=new FragmentC();
}
return fragment;
}
@Override
public int getCount() {
Log.d("SWIPE","get count is called");
return 3;
}
// talks to title to give the page
@Override
public CharSequence getPageTitle(int position) {
if (position == 0) {
return "Tab 1";
}
if (position == 1) {
return "Tab 2";
}
if (position == 2) {
return "Tab 3";
}
return null;
}
}
片段A
/**
* Created by Luke on 20/04/2015.
*/
public class FragmentA extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_a, container, false);
}
public void doSomething(){
// call this method from main activity
}
}
片段B
/**
* Created by Luke on 20/04/2015.
*/
public class FragmentB extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_a, container, false);
}
}
片段C
/**
* Created by Luke on 20/04/2015.
*/
public class FragmentC extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_a, container, false);
}
}
你可以这样做-
@Override
protected void onResume() {
super.onResume();
FragmentA _fragA = new FragmentA();
_fragA.doSomething();
}
您可以使用以下元素在清单文件中注册接收器:
<receiver android:name="MyReceiver" >
<intent-filter>
<action android:name="com.example.Broadcast" >
</action>
</intent-filter>
</receiver>
嵌套元素用于指定接收者应对的事件。
仅供参考,您的问题并非特定于使用 ViewPager。
根据设计,activity 除了 FragmentA 是一个 Fragment 之外对它一无所知,因此它不知道它包含 doSomething() 方法。快速而肮脏的方法是从适配器获取片段并在知道它是 FragmentA 时将其转换为 FragmentA。我说这是一种 "quick and dirty" 方式,因为你希望在 activity 和片段之间保持分离——即您的 activity 不需要了解您的 FragmentA 实现,只需要了解 Fragment。
当您构建更复杂的应用程序时,您需要研究使用事件总线以一种很好的解耦方式在片段和活动之间发送消息。以下是一些流行的 android 事件总线: http://square.github.io/otto/ https://github.com/greenrobot/EventBus