hiwa doski Ответов: 2

Почему мой фрагмент все еще равен нулю, даже если я был добавлен менеджером фрагментов?


почему мой фрагмент " f1 "все еще равен нулю, хотя я добавил фрагмент в свое представление с помощью "FragmentManager"


MainActivivty.java


    public class MainActivity extends AppCompatActivity implements FragmentA.Communicator {


    FragmentManager manager;
    FragmentA f1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        manager = getSupportFragmentManager();

        Fragment fragment = manager.findFragmentById(R.id.main_fragment_container);
        if (fragment == null) {
            fragment = new FragmentA();
            manager.beginTransaction()
                    .add(R.id.main_fragment_container, fragment)
                    .commit();
        }

        f1 = (FragmentA) manager.findFragmentById(R.id.main_fragment_container);
        f1.setCommunicator(this);

    }

    @Override
    public void changeText(String text) {
        FragmentB f2 = (FragmentB) manager.findFragmentById(R.id.details_fragment_container);

        if (f2 != null && f2.isVisible()) {
            f2.updateText(text);
        } else {
            Intent intent = new Intent(MainActivity.this, DetailsActivity.class);
            intent.putExtra("text", text);
            startActivity(intent);
        }
    }
}


<big>activity_main.xml</big>

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/main_fragment_container" />

</LinearLayout>


DetailsActivity.java 

    public class DetailsActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_details);

        Intent intent = getIntent();
        String recievedText = intent.getStringExtra("text");
        FragmentB f2 = (FragmentB) getSupportFragmentManager().findFragmentById(R.id.details_fragment_container);
        if (f2 != null) {
            f2.updateText(recievedText);
        }

    }
}



details_activity.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.dandroid.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".DetailsActivity">

    <fragment
        android:id="@+id/details_fragment_container"
        android:layout_width="wrap_content"
        android:name="com.example.workout.FragmentB"
        android:layout_height="wrap_content" />

</LinearLayout>



    FragmentA.java

    public class FragmentA extends Fragment {

    Communicator communicator;
    ListView listView;

    public FragmentA() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment


        View view = inflater.inflate(R.layout.fragment_a, container, false);
        listView = view.findViewById(R.id.listview);
        return view;
    }

    public void setCommunicator(Communicator communicator) {
        this.communicator = communicator;
    }

     @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        final ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("first row");
        arrayList.add("second row");
        arrayList.add("third row");

        ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1,
                arrayList);
        listView.setAdapter(adapter);

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                communicator.changeText(arrayList.get(position));
            }
        });
    }

    public interface Communicator {
        void changeText(String text);
    }
}


fragment_a.xml

    <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".FragmentA">

 <ListView
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:id="@+id/listview" />

</FrameLayout>

Log:

    
       java.lang.NullPointerException: Attempt to invoke virtual method 'void 
        com.example.workout.FragmentA.setCommunicator(com.example.workout.FragmentA$Communicator)' 
        on a null object reference
         Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void 
        com.example.workout.FragmentA.setCommunicator(com.example.workout.FragmentA$Communicator)' 
        on a null object reference
        at com.example.workout.MainActivity.onCreate(MainActivity.java:33)
        at android.app.Activity.performCreate(Activity.java:7136)
        at android.app.Activity.performCreate(Activity.java:7127)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 


Что я уже пробовал:

я много чего перепробовал, но ничего не вышло.

Richard MacCutchan

Вы должны проверить, что возвращается менеджером фрагментов для f1. Лучший способ сделать это - пройтись по коду с помощью отладчика.

hiwa doski

я исправил это, изменив
f1 = (FragmentA) manager.findFragmentById(R. id.main_fragment_container);
к
f1 = (фрагмент) фрагмент;

и это сработало, но я не знаю, правильно ли это делать.

Richard MacCutchan

Извините, не могу сказать. Но вы все равно должны попытаться выяснить, почему первый вызов не удается.

hiwa doski

ладно, спасибо.

Richard MacCutchan

См. мое решение ниже.

2 Ответов

Рейтинг:
2

Richard MacCutchan

Я думаю, что это проблема:

Fragment fragment = manager.findFragmentById(R.id.main_fragment_container);
if (fragment == null) {
    fragment = new FragmentA();
    manager.beginTransaction()
            .add(R.id.main_fragment_container, fragment)
            .commit();
}

f1 = (FragmentA) manager.findFragmentById(R.id.main_fragment_container);
f1.setCommunicator(this);

В первую очередь если manager.findFragmentById возвращается null затем вы создаете новый FragmentA объект. Но во втором случае вы не проверяете, получили ли вы действительный объект. И глядя на XML, я подозреваю, что фактический идентификатор, который объявлен, не распознается как идентификатор фрагмента.


hiwa doski

Спасибо, но проблема в том, почему он не получает действительный объект, если я сделаю еще одну проверку, то он будет игнорировать мои утверждения, потому что " f1 "все равно будет нулевым, и я проверил id несколько раз, что это один и тот же объект, "FragmentManager" добавляет к нему и `f1` получает от него.

Richard MacCutchan

Как я уже упоминал выше, наиболее вероятно, что поиск R.id.main_fragment_container по какой-то причине терпит неудачу. Это то, что вам нужно исследовать.

hiwa doski

да, я нашел ответ, и это потому, что `commit()` является асинхронным, и мне нужно использовать `committnow()` вместо этого

Рейтинг:
1

OriginalGriff

Потому что он не может найти ваш фрагмент с этим идентификатором: FragmentManager  |  Разработчики Android[^]

Цитата:
Возвращается
Fragment	The fragment if found or null otherwise.
Поэтому используйте отладчик и посмотрите, что на самом деле представляет собой строка идентификатора, которую вы пытаетесь найти.


hiwa doski

я исправил это, изменив
f1 = (FragmentA) manager.findFragmentById(R. id.main_fragment_container);
к
f1 = (фрагмент) фрагмент;

и это сработало, но я не знаю, правильно ли это делать.