W poniższym kodzie próbowałem odczytać dane z Firebase i użyć ich do dynamicznego tworzenia widoków kart, ale kiedy program się uruchamia, ArrayList jest pusta, gdy klikam trzecią kartę i wracam do pierwszej. Po kilku dniach od znalezienia problemu sam nie potrafiłem go rozwiązać. 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 odpowiedź
Zanim przejdziesz przez m2.jaratok
, dane nie są jeszcze dostępne i dlatego Twoja lista jest pusta. Interfejsy API Firebase to asynchronous
, co oznacza, że metoda onDataChange()
powraca natychmiast po jej wywołaniu, a wywołanie zwrotne z zadania, które zwraca, zostanie wywołane jakiś czas później.
Nie ma gwarancji, jak długo to potrwa, może upłynąć od kilkuset milisekund do kilku sekund, zanim dane będą dostępne i mogą być używane. Ponieważ ta metoda zwraca natychmiast, twoja lista jaratok
, której próbujesz użyć poza wywołaniem zwrotnym, jest pusta.
Zasadniczo próbujesz użyć wartości synchronicznie z interfejsu API, który jest asynchroniczny. To nie jest dobry pomysł. Interfejsy API należy obsługiwać asynchronicznie zgodnie z przeznaczeniem.
Szybkim rozwiązaniem tego problemu byłoby użycie listy jaratok
tylko wewnątrz metody onDataChange()
, w przeciwnym razie polecam zobaczyć ostatnią część mojej odpowiedzi z tego post, w którym wyjaśniłem, jak to można to zrobić za pomocą niestandardowego wywołania zwrotnego. Możesz również obejrzeć ten film, aby uzyskać lepsze zrozumienie.
Podobne pytania
Powiązane pytania
Nowe pytania
java
Java to język programowania wysokiego poziomu. Użyj tego tagu, jeśli masz problemy z używaniem lub zrozumieniem samego języka. Ten tag jest rzadko używany samodzielnie i jest najczęściej używany w połączeniu z [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] i [maven].