Фрагмент Android на CreateView задерживается - PullRequest
0 голосов
/ 22 декабря 2019

Справочная информация и проблема:

У меня есть пользовательский класс Fragment. Я повторно использую этот фрагмент класса для нескольких отображений статуса. В родительском Activity я загружаю фрагмент и вызываю метод для фрагмента текста и т. Д. Когда я делаю это, я нажимаю NullPointerException. Причина в том, что onCreateView () еще не был вызван, т. Е. Представление не существует, поэтому доступ к TextView для вызова .setText(String), безусловно, приведет к NullPointerException.

Класс фрагмента

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.example.app.R;

public class CopyStaticFragment extends Fragment {

    private String initialActionText, initialSecondaryText, initialTitleText;
    private TextView textViewTitle, textViewSecondary;
    private Button btnAction;
    private View.OnClickListener actionCallback;

    public void setActionButtonListener(View.OnClickListener actionCallback) {
        this.actionCallback = actionCallback;
    }

    public CopyStaticFragment() {
    }

    public CopyStaticFragment(View.OnClickListener actionCallback) {
        this.actionCallback = actionCallback;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View layout = inflater.inflate(R.layout.fragment_main_status, container, false);

        textViewTitle = layout.findViewById(R.id.textViewTitle);
        textViewTitle.setText(initialTitleText);
        textViewSecondary = layout.findViewById(R.id.textViewSecondary);
        textViewSecondary.setText(initialSecondaryText);
        btnAction = layout.findViewById(R.id.btnAction);
        btnAction.setText(initialActionText);
        btnAction.setOnClickListener(v -> {
            if(actionCallback != null) {
                actionCallback.onClick(v);
            }
        });

        return layout;
    }

    public void setPrimaryText(String text) {
        textViewTitle.setText(text);
    }

    public void setSecondaryText(String text) {
        textViewSecondary.setText(text);
    }

    public void setActionText(String text) {
        btnAction.setText(text);
    }

    public void setInitialActionText(String text) {
        this.initialActionText = text;
    }

    public void setInitialSecondaryText(String text) {
        this.initialSecondaryText = text;
    }

    public void setInitialTitleText(String text) {
        this.initialTitleText = text;
    }

}

Где-то в моей основной деятельности, в качестве ответа на обратный вызов из состояния Service, я сделаю что-то вроде:

if (instance.getUnbackedUpCount() > 0) {
    // Load first fragment - i.e. we can backup content
    getSupportFragmentManager().beginTransaction()
            .replace(R.id.frameCurrentStatus, copyStartFragment)
            .commit();
    capacityControlFragment.setInfoIconVisible(true);
} else {
    getSupportFragmentManager().beginTransaction()
            .replace(R.id.frameCurrentStatus, copyFinishFragment)
            .commit();
}

где copyStartFragment & copyFinishFragment являются экземплярами вышеупомянутого фрагмента.

Примечание:

В зависимости от интервала обновления статуса Service, вызов фрагментов replace() может быть почти мгновенным - что я считаюактуальная проблема.

Мой обходной путь:

Должен иметь начальные сеттеры для всех представлений и их свойств. например, initialTitleText, initialMessageText, initialActionButtonText, initialActionButtonVisibility и т. д. Я чувствую, что это хакерский и не соответствует предполагаемой философии дизайна использования фрагментов.

Мой вопрос

Это проблема с моей стороны, связанная с такой ошибкой, или есть обходной путь для вызова onCreateView() раньше?

Ответы [ 2 ]

1 голос
/ 22 декабря 2019

Вы используете .commit() как часть замены фрагментов.
Это делается асинхронно. Обойти это невозможно, просто работает эта функция.

Вы можете использовать .commitNow(), и будет выполнена синхронизация.
Сделав это таким образом, вы сможете мгновенно получить доступ к представлениям. после возврата из функции.

https://developer.android.com/reference/androidx/fragment/app/FragmentTransaction#commitNow()

0 голосов
/ 23 декабря 2019

Передайте начальные строки фрагменту, используя рекомендуемый способ инициализации фрагмента:

public static CopyStaticFragment newInstance(String initialString....) {
    CopyStaticFragment fragment = new CopyStaticFragment();
    Bundle args = new Bundle();
    args.putString(INITIAL_STRING, initialString);

    fragment.setArguments(args);
    return fragment;
}

Затем в onCreate:

 @Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        mInitialString = getArguments().getString(INITIAL_STRING);
    }
}

Затем, когда вы установите TextView текст в OnViewCreated, доступна строка и любые другие параметры.

Инициализируйте свой фрагмент в упражнении, используя:

CopyStaticFragment.newInstance("initial string",....);

Примечание: onCreateView следует использовать только для раздувания вашего ресурса макета, используйте OnViewCreated для инициализации ваших представлений после того, как макет был надут.

Держитесь как можно дальше от commitNow() и popBackStackImmediate() если не любишь IllegalStateException

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...