В активности с вкладками получение данных из Firebase не работает хорошо - PullRequest
0 голосов
/ 18 ноября 2018

В следующем коде я попытался прочитать данные из Firebase и использовать это для динамического создания карт, но при запуске программы ArrayList пуст, пока я нажимаю на третью вкладку и возвращаюсь к первой. После нескольких дней обнаружения проблемы я не мог решить это самостоятельно. MainScreen.java:

public class MainScreen extends AppCompatActivity {

private SectionsPagerAdapter mSectionsPagerAdapter;

private ViewPager mViewPager;
private static final String TAG = "MainScreen";
public List<BusNumber> jaratok= new ArrayList<>();

@Override
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main_screen);
    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
    mViewPager = findViewById(R.id.container);
    mViewPager.setAdapter(mSectionsPagerAdapter);

    TabLayout tabLayout = findViewById(R.id.tabs);
    tabLayout.getTabAt(0).setText("Járatok");
    tabLayout.getTabAt(1).setText("Megállók");
    tabLayout.getTabAt(2).setText("Tervező");

    FirebaseDatabase database = FirebaseDatabase.getInstance();
    DatabaseReference myRef = database.getReference("bus_number");
    myRef.addValueEventListener((new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            jaratok = new ArrayList<>();
            for(DataSnapshot ds : dataSnapshot.getChildren()) {
                jaratok.add(new BusNumber(ds.child("CodeNumber").getValue(String.class),ds.child("BusRouteName").getValue(String.class)));
            }
        }
        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            Log.w("TAG","Failed to read data.",databaseError.toException());
        }
    }));
    mSectionsPagerAdapter.notifyDataSetChanged();

    mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
    tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));

    FloatingActionButton fab = findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Fejlesztés alatt", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });

}
public class SectionsPagerAdapter extends FragmentPagerAdapter {

    public SectionsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {

        switch(position)
        {
            case 0:
                JaratokTab1 tab1 = new JaratokTab1();
                return tab1;
            case 1:
                MegallokTab2 tab2 = new MegallokTab2();
                return tab2;
            case 2:
                TervezoTab3 tab3 = new TervezoTab3();
                return tab3;

            default:
                return null;
        }
    }

}

JaratokTab1.java:

public class JaratokTab1 extends Fragment {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    final View rootView = inflater.inflate(R.layout.jaratok_tab1, container, false);
    MainScreen m2 = (MainScreen) getActivity();
    for (BusNumber n : m2.jaratok) {
        Log.d("Ertek: ", n.getName());
    }
    CardView cardView = new CardView(getContext());
    TextView tv = new TextView(getContext());
    FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
    tv.setLayoutParams(params);
    cardView.setLayoutParams(params);
    cardView.setVisibility(View.VISIBLE);
    cardView.setCardElevation(9);
    cardView.setPadding(15, 15, 15, 15);
    cardView.setRadius(9);
    tv.setTextColor(Color.RED);
    tv.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
    cardView.addView(tv);
    LinearLayout linearLayout = rootView.findViewById(R.id.linearID);
    linearLayout.setPadding(60,15,50,30);
    linearLayout.addView(cardView);
    return rootView;
}
//also tried this:
   /* @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        MainScreen m2 = (MainScreen) getActivity();
        for (BusNumber n : m2.jaratok) {
            Log.d("Ertek: ", n.getName());
        }
    }*/
}

1 Ответ

0 голосов
/ 19 ноября 2018

К тому времени, когда вы просматриваете m2.jaratok, данные еще не доступны, и поэтому ваш список пуст. API Firebase имеют значение asynchronous, что означает, что метод onDataChange() возвращается сразу после его вызова, а обратный вызов из Задачи, которую он возвращает, будет вызван через некоторое время.

Нет никакой гарантии, сколько времени это займет, может пройти от нескольких сотен миллисекунд до нескольких секунд, прежде чем эти данные станут доступны и могут быть использованы. Поскольку этот метод немедленно возвращается, ваш список jaratok, который вы пытаетесь использовать вне обратного вызова, пуст.

По сути, вы пытаетесь использовать значение синхронно из API, который является асинхронным. Это не очень хорошая идея. Вы должны обрабатывать API-интерфейсы асинхронно, как и предполагалось.

Быстрое решение этой проблемы - использовать список jaratok только внутри метода onDataChange(), в противном случае я рекомендую вам просмотреть последнюю часть моего ответа от этого сообщения в котором я объяснил, как это можно сделать с помощью пользовательского обратного вызова. Вы также можете взглянуть на это видео для лучшего понимания.

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