Вместо того, чтобы бросать код на вас, есть два понятия, которые являются ключом к пониманию того, как JS обрабатывает обратные вызовы и асинхронность. (это даже слово?)
Есть три вещи, о которых вам нужно знать; Очередь; цикл события и стек
. В широких упрощенных терминах цикл событий подобен диспетчеру проекта, он постоянно прослушивает любые функции, которые хотят запускать и взаимодействовать между очереди и стека.
while (queue.waitForMessage()) {
queue.processNextMessage();
}
Как только он получает сообщение для запуска чего-то, он добавляет его в очередь. Очередь - это список вещей, которые ждут выполнения (например, ваш запрос AJAX). Представьте себе это так:
1. call foo.com/api/bar using foobarFunc
2. Go perform an infinite loop
... and so on
Когда одно из этих сообщений будет исполнено, оно выталкивает сообщение из очереди и создает стек, стек - это все, что нужно выполнить JS для выполнения инструкции в сообщение. Таким образом, в нашем примере ему говорят позвонить foobarFunc
function foobarFunc (var) {
console.log(anotherFunction(var));
}
. Так что все, что foobarFunc должно выполнить (в нашем случае anotherFunction
), будет вставлено в стек. исполняемый, а затем забытый - цикл события затем переместится на следующую вещь в очереди (или прослушивает сообщения)
. Главное здесь - порядок выполнения. Это
Когда вы совершаете вызов с использованием AJAX для внешней стороны или выполняете любой асинхронный код (например, setTimeout), Javascript зависит от ответ, прежде чем он сможет продолжить.
Большой вопрос, когда он получит ответ? Ответ в том, что мы не знаем, поэтому цикл событий ждет, когда это сообщение скажет: «Эй, забери меня». Если JS просто ждал этого сообщения синхронно, ваше приложение замерзнет, и оно сосать. Таким образом, JS продолжает выполнение следующего элемента в очереди, ожидая, пока сообщение не будет добавлено обратно в очередь.
Вот почему с асинхронной функциональностью мы используем вещи, называемые обратными вызовами. Это похоже на обещание буквально. Как и в I , обещание что-то вернуть в какой-то момент jQuery использует специальные обратные вызовы, называемые deffered.done
deffered.fail
и deffered.always
(среди других). Вы можете увидеть их все здесь
Итак, вам нужно передать функцию, которая в какой-то момент будет выполнена с переданными ей данными.
Поскольку обратный вызов не выполняется немедленно, но в более позднее время важно передать ссылку на функцию, которую она не выполнила. поэтому
function foo(bla) {
console.log(bla)
}
, поэтому большую часть времени (но не всегда) вы пройдете foo
не foo()
. Надеюсь, это будет иметь смысл. Когда вы сталкиваетесь с такими вещами, которые кажутся запутанными, я настоятельно рекомендую полностью прочитать документацию, чтобы хотя бы понять ее. Это сделает вас намного лучшим разработчиком.
Я не понимаю, что делать в Df, когда «OK» нажата, чтобы удалить фрагменты Df, Cf и Bf?
blockquote>Шаг # 1 : Дайте Df сказать D "yo! Мы получили ОК нажмите!" путем вызова метода либо по самой операции, либо по экземпляру интерфейса, предоставленному активностью.
Шаг # 2: У D удалите фрагменты с помощью
FragmentManager
.Хозяйственная деятельность (D) - это та, которая знает, какие другие фрагменты в действии (в отличие от других видов деятельности). Следовательно, события с фрагментами, которые могут повлиять на фрагмент-микс, должны быть распространены на активность, что приведет к соответствующим ходам оркестровки.
Вы должны позволить Управлению заниматься добавлением и удалением фрагментов, как говорит CommonsWare, использовать прослушиватель. Вот пример:
public class MyActivity extends FragmentActivity implements SuicidalFragmentListener {
// onCreate etc
@Override
public void onFragmentSuicide(String tag) {
// Check tag if you do this with more than one fragmen, then:
getSupportFragmentManager().popBackStack();
}
}
public interface SuicidalFragmentListener {
void onFragmentSuicide(String tag);
}
public class MyFragment extends Fragment {
// onCreateView etc
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
suicideListener = (SuicidalFragmentListener) activity;
} catch (ClassCastException e) {
throw new RuntimeException(getActivity().getClass().getSimpleName() + " must implement the suicide listener to use this fragment", e);
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Attach the close listener to whatever action on the fragment you want
addSuicideTouchListener();
}
private void addSuicideTouchListener() {
getView().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
suicideListener.onFragmentSuicide(getTag());
}
});
}
}
Вы можете использовать подход ниже, он отлично работает:
getActivity().getSupportFragmentManager().popBackStack();
OnCreate:
//Add comment fragment
container = FindViewById<FrameLayout>(Resource.Id.frmAttachPicture);
mPictureFragment = new fmtAttachPicture();
var trans = SupportFragmentManager.BeginTransaction();
trans.Add(container.Id, mPictureFragment, "fmtPicture");
trans.Show(mPictureFragment); trans.Commit();
Вот как я скрываю фрагмент в событии click 1
//Close fragment
var trans = SupportFragmentManager.BeginTransaction();
trans.Hide(mPictureFragment);
trans.AddToBackStack(null);
trans.Commit();
Затем показывает его обратно int event 2
var trans = SupportFragmentManager.BeginTransaction();
trans.Show(mPictureFragment); trans.Commit();
В Activity / AppCompatActivity:
@Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
// if you want to handle DrawerLayout
mDrawerLayout.closeDrawer(GravityCompat.START);
} else {
if (getFragmentManager().getBackStackEntryCount() == 0) {
super.onBackPressed();
} else {
getFragmentManager().popBackStack();
}
}
}
, а затем вызовите фрагмент:
getActivity().onBackPressed();
или как указано в других ответах, вызовите это в фрагмент:
getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
Если вам нужно сбрасывать четвертый фрагмент из истории backstack в первый, используйте теги !!!
Когда вы добавляете первый фрагмент, вы должны использовать что-то вроде этого:
getFragmentManager.beginTransaction.addToBackStack ("A"). add (R.id.container, FragmentA) .commit ()
или
getFragmentManager.beginTransaction.addToBackStack ("A ") .replace (R.id.container, FragmentA) .commit ()
И если вы хотите показать фрагменты B, C и D, вы используете это:
getFragmentManager.beginTransaction .addToBackStack ("B"). replace (R.id.container, FragmentB, "B"). commit ()
и другие буквы ....
Чтобы вернуться к Фрагмент A, просто вызовите popBackStack (0, «A»), да, используйте флаг, который вы указали при его добавлении, и обратите внимание, что он должен быть тем же самым флажком в команде addToBackStack, а не тот, который используется в команде replace или add .
Добро пожаловать;)
Я создаю простой метод для этого
popBackStack(getSupportFragmentManager());
. Поместите его в мой класс ActivityUtils
public static void popBackStack(FragmentManager manager){
FragmentManager.BackStackEntry first = manager.getBackStackEntryAt(0);
manager.popBackStack(first.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
. Он отлично работает, получайте удовольствие!
Хотя это может быть не самый лучший подход, ближайший эквивалент, я могу думать, что это работает с библиотекой поддержки / совместимости
getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
или
getActivity().getFragmentManager().beginTransaction().remove(this).commit();
в противном случае .
Кроме того, вы можете использовать backstack и всплывать. Однако имейте в виду, что фрагмент, возможно, не находится в задней части (в зависимости от фрагментации, который получил его там.), Или это может быть не последний, который попал в стек, поэтому выталкивание стека может удалить неправильный ...
Посмотрите, удовлетворяются ли ваши потребности с помощью DialogFragment. DialogFragment имеет метод увольнения (). На мой взгляд, гораздо более чистым.