我正在尝试用android实现滑动视图。我正在使用带有两个包含片段的选项卡的ViewPager。在我的onCreate()方法中,我试图从sharedPrefferences中读取并根据我得到的内容,我想要更改第一个片段的父视图的一些子视图的文本和可见性。不幸的是,当我尝试访问片段视图时,我总是得到NullPointerException。
下面给出了来自两个片段之一的示例代码。请你帮助我好吗 ?有没有更好的方法呢?
MainActivity:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
actionBar = getActionBar();
context = getApplicationContext();
myTabPagerAdapter = new TabPagerAdapter(getSupportFragmentManager());
myViewPager = (ViewPager) findViewById(R.id.pager);
myViewPager.setAdapter(myTabPagerAdapter);
myViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
Toast.makeText(MainActivity.this, "Selected page position: " + position, Toast.LENGTH_SHORT).show();
getActionBar().setSelectedNavigationItem(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
@Override
public void onTabReselected(android.app.ActionBar.Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
myViewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(android.app.ActionBar.Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
};
actionBar.addTab(actionBar.newTab().setText("Spot Position").setTabListener(tabListener));
actionBar.addTab(actionBar.newTab().setText("Track Vehicle").setTabListener(tabListener));
//Get saved latitude and longitude from sharedPreferences
sharedPref = context.getSharedPreferences("net.ddns.drimou.bachelorthesis", Context.MODE_PRIVATE);
editor = sharedPref.edit();
}
@Override
protected void onStart() {
super.onStart();
getSharedPreferencesOnStart();
}
public void getSharedPreferencesOnStart() {
String s = myTabPagerAdapter.makeFragmentName(myViewPager.getId(),myViewPager.getCurrentItem());
SpotPosition sp = (SpotPosition) myTabPagerAdapter.getItem(0);
sp.setSettings();//In this call i am getting null pointer
...}
片段A
public class SpotPosition extends Fragment {
TextView locationTextView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View spotPosition = inflater.inflate(R.layout.spot_position, container, false);
return spotPosition;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
public void setSettings(){
locationTextView = (TextView) myView.findViewById(R.id.mainTextView);//NullPointerException here
locationTextView.setVisibility(View.VISIBLE);
locationTextView.setText("Hello");
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public void onDestroyView() {
super.onDestroyView();
}
TabPagerAdapter
public class TabPagerAdapter extends FragmentPagerAdapter {
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
private View mCurrentView;
private SpotPosition sp = null;
private static int NUM_ITEMS = 2;
public TabPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int i) {
switch (i) {
case 0:
//Fragment for SpotPosition myViewPager
return new SpotPosition();
case 1:
//Fragment for TrackVehicle myViewPager
return new TrackVehicle();
}
return null;
}
@Override
public int getCount() {
return NUM_ITEMS; //Number of Tabs
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
sp = (SpotPosition)object;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
@Override
public CharSequence getPageTitle(int position) {
switch(position) {
case 0:
return "Spot Position";
case 1:
return "Track Vehicle";
default:
return null;
}
}
public String makeFragmentName(int viewId, int index) {
return "android:switcher:" + viewId + ":" + index;
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
public View getCurrentView(){
return this.mCurrentView;
}
public SpotPosition getCurrentSpotPosition(){
return this.sp;
}
随意询问是否有不明白的事情。谢谢
答案 0 :(得分:1)
据我了解,您可以从您的活动中调用setSettings,以更改片段中的视图。您没有提供堆栈跟踪,我认为您有问题 - 尝试在offcreen片段中调用onPause后更改视图。有几种方法可以解决它。 首先,不要直接打电话给观点 关于活动
public void getSharedPreferencesOnStart() {
String s = myTabPagerAdapter.makeFragmentName(myViewPager.getId(),myViewPager.getCurrentItem());
SpotPosition sp = (SpotPosition) myTabPagerAdapter.getItem(0);
// sp.setSettings();//In this call i am getting null pointer
SharedPreferences prefs = getSharedPreferences("message",MODE_PRIVATE);
Editor editor = prefs.edit();
editor.putBoolean("say_hello",true")
editor.commit();
...}
片段中的
@Override
public void onResume(){
super.onResume();
SharedPreferences prefs =
getActivity().getSharedPreferences("message", Context.MODE_PRIVATE);
{
//this block is used for offsreen fragment, it will get update, when it go to forescreen
boolean sayHello = prefs.getBoolean("say_hello", false);
if(sayHello){
locationTextView =
(TextView) myView.findViewById(R.id.mainTextView);//NullPointerException here
locationTextView.setVisibility(View.VISIBLE);
locationTextView.setText("Hello");
}else{
// say something elese
}
}
{
//this listener is for forescreen fragment, as soon as shared preferences will be updated,
// listerner willbe called and you can update your view depending on changed parameters
prefs.registerOnSharedPreferenceChangeListener(
new OnSharedPreferenceChangeListener(){
@Override
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key
){
if(key.equals("say_hello")){
boolean sayHello = sharedPreferences.getBoolean("say_hello", false);
if(sayHello){
locationTextView =
(TextView) myView.findViewById(R.id.mainTextView);//NullPointerException here
locationTextView.setVisibility(View.VISIBLE);
locationTextView.setText("Hello");
}else{
// say something elese
}
}
}
}
);
}
}
你也可以使用Otto bus它仍然不能用于片段通信的活动,因为片段可以处于!isResumed
状态,但它对片段 - 活动通信很有用。
如果您需要对每个片段和活动进行单独的复杂状态跟踪,我建议使用sqlDatabase and CursorLoaders。它会让你很好地控制状态和实时通信。
编辑:
并不是说你不能通过getter将视图从片段传递给活动
问题 - 您无法保证,您完全了解片段的状态和视图。您尝试更新之前调用的onStart
活动视图,然后片段s
onStart , because fragment have to be generated by adapter and go through attachement process. (to find yout if fragment is attached to activity, you have to set listener in activity and call it on
onActivityAttached`片段。请参阅使用片段模板的android studio活动。因此,当您调用更改视图时,片段和视图可能不存在
此外,您应该阅读有关片段和活动生命周期的内容并阅读有关上下文的信息(尤其是为什么在不相关的上下文持有者中强引用视图会导致严重的内存泄漏和错误的错误