尝试通过接口修改片段GUI项时出现空指针异常

时间:2015-04-24 15:18:44

标签: android

我有一个包含ViewPager的活动,其中包含3个片段。 当活动获取位置信息时(在onConnected方法中),我希望它将信息传递给一个片段,该片段应该更改其TextView的内容。

我使用在MainActivity中创建的接口实现了信息传递,而且片段实现了获取位置信息和修改TextView所需的方法。

问题出现了:实现的方法在调用时似乎找不到TextView,并且它上升了NullpointerException

public class FragmentTab4 extends Fragment implements MainActivity.LocationHandler {

    View view;
    TextView textView;
    public TextView location;
    public Context context;
    ListView listViewMessages22;
    MessageLayoutAdapter adapter;
    Button writeMessageButton;
    private Bundle args = new Bundle();
    protected GoogleApiClient mGoogleApiClient;

    private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
    private LocationRequest mLocationRequest;

    //public static final String TAG = FragmentTab4.class.getSimpleName();
    public static final String TAG = MainActivity.class.getSimpleName();

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        // Get the view from fragmenttab2.xml
        view = inflater.inflate(R.layout.fragmenttab4, container, false);
        context = getActivity();
        writeMessageButton = (Button) view.findViewById(R.id.buttonWriteMessage);
        writeMessageButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                Toast.makeText(view.getContext().getApplicationContext(), "Button clicked", Toast.LENGTH_SHORT).show();
                //open popup to write message
                WriteMessageDialog writeMessageDialog = new WriteMessageDialog();
                writeMessageDialog.setArguments(args);
                writeMessageDialog.show(getFragmentManager(), "iuuu" );
            }
        });
        location = (TextView) view.findViewById(R.id.textView_location);
        //Location loc = LocationService.getInstance(getActivity()).getLocation();
        location.setText("Getting location...");

        if(((MainActivity)context).mLastLocation!=null){

            Location ll = ((MainActivity)context).mLastLocation;
            location.setText("Coordinates: "+ll.getLatitude()+" "+ll.getLongitude());
        }else{

            location.setText("Nothing...");
        }
        //location.setText("Coordinats: "+loc.getLatitude()+" "+loc.getLongitude());
        //textView = (TextView) view.findViewById(R.id.textView);
        listViewMessages22 = (ListView) view.findViewById(R.id.listViewMessages20);
        List<Message> bacheca1 = new ArrayList<Message>();

        //adapter = new MessageLayoutAdapter(container.getContext(), R.layout.message, bacheca1);
        Log.d(TAG,"Adapter ok.............");
        //listViewMessages22.setAdapter(adapter);
        Log.d(TAG," ok .............");

        return view;
    }

    @Override
    public void handleNewLocation(Location loc) {

        //location.setText("Coordinates: "+loc.getLatitude()+" "+loc.getLongitude());
        Log.d(TAG,"Siamo giunti in Fragment4 - handleNewLocation "+loc.getLatitude()+" "+loc.getLongitude());
        location = (TextView) view.findViewById(R.id.textView_location);
    }

这是MainActivity Class

public class MainActivity extends FragmentActivity implements
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener,
    LocationListener{

    ActionBar actionBar;
    ViewPager viewPager;
    Context context1;
    private LocationRequest mLocationRequest;
    public Location mLastLocation;
    ViewPagerAdapter viewPagerAdapter;

    public static final String TAG = MainActivity.class.getSimpleName();
    protected GoogleApiClient mGoogleApiClient;
    private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;

    LocationHandler mLocationHandler;
    LocationService locator;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context1 = getApplicationContext();
        viewPager = (ViewPager) findViewById(R.id.pager);
        viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(viewPagerAdapter);

        // Create the LocationRequest object
        mLocationRequest = LocationRequest.create().setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY).setInterval(10 * 1000)        // 10 seconds, in milliseconds
            .setNumUpdates(20)
            .setFastestInterval(1 * 1000); // 1 second, in milliseconds

        locator = LocationService.getInstance(this);

        if(!checkPlayServices()){

            finish();
        }
        //create GoogleApiClient
        buildGoogleApiClient();
        //locator.setGoogleClient(mGoogleApiClient);

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {

            mLocationHandler = (LocationHandler) viewPagerAdapter.getItem(0);
        } catch (ClassCastException e){

            Log.d(TAG, "=== Problem connecting the fragment to the activity ===");
            e.printStackTrace();
        }
    }

    @Override
    public void onConnected(Bundle bundle) {

        Log.d(TAG, "On connected........||||||||||||");
        getLocation();
        //viewPager.setAdapter(viewPagerAdapter);
        if(mLastLocation!=null){

            mLocationHandler.handleNewLocation(mLastLocation);
            //locator.setLocation(mLastLocation);
        }else{

            mLocationHandler.alertMissingLocation();
        }

        //FragmentTab4 fragment = (FragmentTab4) viewPagerAdapter.getItem(0);
        //fragment.alertMissingLocation();
    }

这是日志输出:

04-24 17:30:10.121  30668-30668/? D/MainActivity﹕ On Location changed....
04-24 17:30:10.131  30668-30668/? D/MainActivity﹕ requested new loc
04-24 17:30:10.131  30668-30668/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.vlaveglia.appwithtab, PID: 30668
java.lang.NullPointerException
        at        com.example.vlaveglia.appwithtab.bacheca.FragmentTab4.handleNewLocation(FragmentTab4.java:102)
        at com.example.vlaveglia.appwithtab.MainActivity.onLocationChanged(MainActivity.java:169)
        at com.google.android.gms.internal.zzpe$zza.handleMessage(Unknown Source)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        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 dalvik.system.NativeStart.main(Native Method)

ViewPager

public class ViewPagerAdapter extends FragmentStatePagerAdapter {
final int PAGE_COUNT = 4;
// Tab Titles
private String tabtitles[] = new String[] { "Bacheca", "Annunci", "Mappa" , "Prova4"};
Context context;
public ViewPagerAdapter(FragmentManager fm) {
    super(fm);
}
@Override
public int getCount() {
    return PAGE_COUNT;
}
@Override
public Fragment getItem(int position) {
    switch (position) {
        // Open FragmentTab1.java
        case 3:
            FragmentTab1 fragmenttab1 = new FragmentTab1();
            return fragmenttab1;
        // Open FragmentTab2.java
        case 1:
            FragmentTab2 fragmenttab2 = new FragmentTab2();
            return fragmenttab2;
        // Open FragmentTab3.java
        case 2:
            FragmentTab3 fragmenttab3 = new FragmentTab3();
            return fragmenttab3;
        case 0:
            FragmentTab4 fragmenttab4 = new FragmentTab4();
            return fragmenttab4;
    }
    return null;
}
@Override
public CharSequence getPageTitle(int position) {
    return tabtitles[position];
}

}

1 个答案:

答案 0 :(得分:0)

这是一个并发问题。此方法public void onConnected(Bundle bundle)GoogleApiClient.ConnectionCallbacks的回调。这不取决于Fragment的可用性。因此,在片段构建其视图之前,可能会过早地调用handleNewLocation

降低接收位置回调时片段不可用的风险的一种方法是在创建片段后启动位置请求。像这样创建一个监听器

public interface MyFragmentListener {
   public void onViewCreated();
}
你在片段中调用的

MyFragmentListener myFragmentListener;

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    myFragmentListener = (MyFragmentListener)activity;
}    

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
   myFragmentListener.onViewCreated();
}

然后在Activity

中实现此侦听器
public class MainActivity extends FragmentActivity implements    
..., MyFragmentListener {

    @Override
    public void onViewCreated(){
        //request location, I believe it's by invoking this method
        if (mGoogleApiClient.isConnected()) {
            mGoogleApiClient.disconnect();
        }
        mGoogleApiClient.connect();
    }
} 

只要您不打算替换或删除片段,那么此方法就可以了。如果你这样做,那么当回调到来时片段可能会消失,引发空指针异常。所以我个人放弃了这个听众概念,因为你看到听众与Activity或Fragment及其生命周期紧密耦合。由于您是Android新手,我建议您花一点时间阅读Publisher-Subscriber模式及其实现,如OttoEventBus

最后不要重新初始化视图(例如,不要多次location = (TextView) view.findViewById(R.id.textView_location);次)。只需在onCreateView中执行一次并直接使用引用(例如location.setText("aaa")