2013-03-15 2 views
1

У меня странная проблема. Я использую Fragments в приложении с хостом FragmentActivity, в котором я реализовал внутренний class FragmentPagerAdapater, который создает фрагменты и помещает их в вкладки моей активности.Fragment's onCreateView() заставляет мое приложение разбиться

В приложении мне нужно передать объект из моей активности в фрагменты. Я не совсем уверен, какой правильный способ сделать это, поэтому я импровизировал и пошел на статический фрагмент newInstance(Object obj) в своих фрагментах. Этот метод просто вызывает конструктор Fragment по умолчанию и устанавливает переменную экземпляра для хранения объекта внутри фрагмента.

Теперь в методе Фрагмента createView() я использую информацию об объекте экземпляра, чтобы заполнить макет. Это отлично работает, когда приложение запускается, но приложение падает, когда я меняю ориентацию экрана с портрета на пейзаж (или наоборот). Журналы указывают на исключение NullPointerException в экземпляре Object в createView(). Я чувствую, что пропустил что-то на жизненном цикле, но я не могу найти ответ. Есть ли что-то особенное, чтобы мои Фрагменты сохранили свою переменную экземпляра, несмотря ни на что?

Вот пример кода, чтобы помочь вам понять, что вопрос:

public class MyFragment extends Fragment { 

private Object obj; 

public static MyFragment newInstance(Object obj) { 
    MyFragment fragment = new MyFragment(); 
    fragment.setObject(obj); 
    return fragment; 
} 

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

    View rootView = inflater.inflate(R.layout.layout_fragment, container, false); 
    MyType res = ((Type) (obj)).getSomething(); // This line causes the crash because obj is null when I switch to another orientation 

    // I Do something with res to fill rootView 

    return rootView; 
} 

private void setObject(Object obj) { 
    this.obj = obj; 
} 
} 


// In the Activity I simply create the Fragment using 
MyFragment fragment = MyFragment.newInstance(myObjectToPass); 

Спасибо за вашу помощь!

+0

мы должны увидеть код! –

+0

crash => трассировка столбца. – njzk2

ответ

2

Когда ориентация переключается (действительно, когда Android решает воссоздать Fragment), существующие Fragment уничтожаются и воссоздаются.

Однако, когда Android воссоздает ваш Fragment, он не вызывает ваш пользовательский метод newInstance(). Он использует пустой конструктор no-args.

Это означает, что ваш Fragmentне будет иметь непустую ссылку на какой-либо обычай Object вы хотите, в результате чего NPE бросает.

Вам необходимо выяснить способ прохождения Object. Если Object - это простые данные Object, рассмотрите возможность передачи своих полей через метод setArguments() или Сериализация.

MyFragment fragment = new MyFragment(); 
Bundle data = new Bundle(); 
data.putString ("key_string", "your string here"); 
fragment.setArguments (data); 

Вы также можете создать interface, запрашивающий активность объекта. Например:

public class MyFragment extends Fragment { 

    public interface ObjectProvider 
    { 
    public CustomObject getCustomObject(); 
    } 

    private ObjectProvider provider; 

    @Override 
    public void onAttach (Activity activity) 
    { 
    super.onAttach(activity); 
    try{ 
     provider = (ObjectProvider) activity;//get an instance of the ObjectProvider 
    } 
    catch (ClassCastException e) 
    { 
     e.printStackTrace(); 
     throw new RuntimeException ("This isn't an ObjectProvider."); 
    } 
    } 

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

    View rootView = inflater.inflate(R.layout.layout_fragment, container, false); 

    provider.getCustomObject().getSomething(); 

    return rootView; 
    } 
} 

Тогда ваша активность должна реализовать интерфейс:

public class MainActivity implements MyFragment.ObjectProvider{ 

@Override 
public CustomObject getCustomObject() 
{ 
    return new CustomObject(); 
} 
} 
+0

Спасибо, он работал как шарм. – francoisr

+0

@francoisr приветствую :-) –

1

Вы также можете просто использовать setRetainInstance (правда), как следующее:

public static MyFragment newInstance(Object obj) { 
    MyFragment fragment = new MyFragment(); 
    fragment.setObject(obj); 
    fragment.setRetainInstance(true); 
    return fragment; 
} 

Это будет сохраняться ваши объект в изменении ориентации, просто убедитесь, что объект не имеет ссылки на контекст активности или у вас будет утечка памяти.

Смежные вопросы