Kotlin - onDataChange nie chce nic zwrócić

0

Witam, chciałbym zwrócić ilość wiadomości z onDatachange i nie potrafię tego zrobić. Prosiłbym o jakieś rady. Jak zrobię w onDatachange uaktualnienie iloscWiadomosc to nie podbija nowej ilości i zwraca zawsze 3 które jest zadeklarowane na początku. return iloscWiadomosc w onDataChange też nie można użyć. Proszę o pomoc

    private fun liczenieWiadomosci():Int{


        
        
        var iloscWiadomosc = 3

        val ref = FirebaseDatabase.getInstance().getReference("/wiadomosci")
        ref.addListenerForSingleValueEvent(object : ValueEventListener{
            override fun onCancelled(p0: DatabaseError) {

            }

            override fun onDataChange(p0: DataSnapshot) {

                iloscWiadomosc = 22
                Log.d("sprawdzam", iloscWiadomosc.toString())

                
            }


        })


        return iloscWiadomosc

    }
2

Nie możesz zwracać wartości z operacji asynchronicznej bez blokowania wątku. ValueEventListener nasłuchuje na wartość pod jakimś węzłem, w Twoim wypadku /wiadomosci, i daje znać, kiedy ta wartość jest odczytana.

Jeżeli chcesz mieć dostęp do aktualnej wartości, to musisz zarejestrować ValueEventListener gdzieś po utworzeniu jakiejś aktywności albo jakiegoś fragmentu. Wtedy możesz reagować odpowiednio na dane w onDataChange dobierając się do nich z parametru p0: DataSnapshot.

Tutaj masz więcej informacji.

0

a jakoś bardziej byś nakierował? nie mogę tego rozkminić

0

Czego konkretnie nie możesz zrozumieć? Wiesz czym jest operacja asynchroniczna?

0

Doczytałem teraz na forum o operacjach asynchronicznych, ale dalej mi to nie rozjaśniło nic

1

Nie wydaje mi się, żeby w dwie minuty dało się doczytać o czymś i to zrozumieć. A asynchroniczność to dosyć złożony temat. Poświęć na to czas i pytaj, jak nie będziesz wiedział czegoś konkretnego.

0

Ciężko coś znaleźć o asynchroniczności w kotlinie, ale ogólnie chodzi o to, że ten kod sobie leci niezależnie od reszty. Tylko nadal nie wiem jak gdzieś zapisać tak prostą informacje jak

 val iloscWiadomosci = p0.children.count().toString()

próbowałem przypisać tą wartość do textView, ale widać najpierw wykonał się kod a dopiero później onDataChange. Musiałbym tą wartość przypisać do czegoś co "poczeka za asynchronicznym kodem" nawet to widać jak ładuje aplikacja, bo dane wypisane z onDataChange nie ładują się tak szybko jak reszta apki. Tylko, że jak w onDataChange ustawie zmiane textu to zmienia, a żeby podłączyć gdzieś te dane to nie mam pojęcia jak.

na stackoverflow każą przekazać te dane do innej funkcji czego też próbowałem, ale jak chcę żeby funkcja zwracała wartość to nie będzie działać, bo w jej parametrze będę musiał podać zawsze jakąś wartość która będzie zczytywana np:

onDataChange{

 val iloscWiadomosci = p0.children.count().toString()
iloscWiadomosciFun(iloscWiadomosci)
}

textView.text = "iloscWiadomosc(1).ToString"

fun iloscWiadomosciFun(iloscWiadomosci: Int){

return iloscWiadomosci

Nie wiem czy jasno napisałem, ale chodzi o po prostu o to, ze jak napisze: TextView.text = "iloscWiadomosciFun(2)" to zawsze bedzie wyswietlac 2, a nie to pobrane z firebase

1

Możesz np. zarejestrować ValueEventListener w miejscu, gdzie masz dostęp do swojego komponentu, który chcesz modyfikować i wtedy go użyć w onDataChange.

0

Jakbyś powiedział jak zarejestrować i odwołać się do ValueEventListener to wiedziałbm wszystko. Szukałem, serio.

próbowałem na różne sposoby. Nie wiem czy to wrzucać, bo jeszcze ktoś pomyśli, że działa

    companion object: ValueEventListener {
        override fun onCancelled(p0: DatabaseError) {
            
        }

        override fun onDataChange(p0: DataSnapshot) {
            
        }

    }
0

Przecież sam w pierwszym poście go rejestrujesz...

0

no tak, ale to działa tylko w jednym jedynym miejscu, a chciałbym tam wsadzić return żeby wyglądało to tak i żeby funkcja zwracała ilość wiadomości które liczy po children.count. tu tak dla przykładu tylko. returna nie da się zrobić, bo zawsze błąd wyrzuca. Jedynie mogę dodać tam textView które się zmieni po załadowaniu, ale to też mnie nie ratuje, bo ta ilość postów ma być wyświetlana w nagłówku fragmentu. jak zadeklaruje zmienną gdzieś wyżej która chciałbym zaaktualizować to się nie aktualizuje ( pewnie reszta kodu wykonuje się szybciej i nie zdąży złapać tej zaaktualizwoanej zmiennej) Jest jakaś możliwość żeby w override fun onDataChange zaaktualizować zmienna która po czasie się zaktualizuje albo wsadzić tam jakoś return?

        override fun onDataChange(p0: DataSnapshot) {

            iloscWiadomosc = 22
            return iloscWiadomosci

        }
2

Możesz tam zaktualizować zmienną i jednocześnie zaktualizować wszystkie widoki. Najlepiej wydzielając to do jakiejś funkcji i wywołać ją w onDataChange.

fun updateMessageCount(count: Int) {
  this.count = count;
  textView.text = "You have $count messages"
  toolbar.title = "Message count: $count"
}
0

To teraz już się całkiem pogubiłem. Tak ładuję nagłówki nawigacji.
chciałbym w zmiennej sprawdz mieć ilość wiadomości, lub zamiast tej zmiennej wstawić jakąś funkcje która zwraca ilość wiadomości więc nie mam jak zaktualizować tego Twoim sposobem, bo tam nie ma żadnego textView do którego mógłbym się odnieść a jeśli w onDataChange prześlę ilość zmiennych do drugiej funkcji to będzie się robić błędne koło, bo funkcja będzie ciągle zwracała to co podam w parametrze, bo bez się nie da funkcji wywołać. Chodzi o to : adapter.addFragmenr(OstatnieWiadomosci(),"funkcjaZwracajacaWiadomosci(2) powiadomień")

tutaj kod nawigacji po fragmentach

        val adapter = ViewPageAdapter(supportFragmentManager)
        adapter.addFragmenr(Wydarzenia(),"Wydarzenia")
        adapter.addFragmenr(Sciana(), "Posty")
        adapter.addFragmenr(Konto_zarzadzanie(), "Ustawienia")
        adapter.addFragmenr(topTygodnia(), "top tygodnia")
        adapter.addFragmenr(TopMiesiaca(), "top miesiaca")
        adapter.addFragmenr(OstatnieWiadomosci(),"$sprawdz powiadomień")

        viewPager.adapter = adapter
        nawigacja.setupWithViewPager(viewPager)
0

Czyżby jedynym wyjściem było wrzucić cały powyższy kod w onDataChange? Takie rozwiązanie słabe mi się wydaje.

1

Nie wiem co to za klasa ViewPagerAdapter, ale zakładam, że przyjmuje jako pierwszy parametr fragment. Masz w takim razie dwa wyjścia.

Pierwsze (gorsze) - wywołać adapter.addFragmenr(OstatnieWiadomosci(),"$sprawdz powiadomień") dopiero w onDataChange z aktualną wartością sprawdz.

Drugie (lepsze) - niech fragment z ostatnimi wiadomościami sam nasłuchuje na ich ilość w Firebase i aktualizuje dynamicznie tę wartość w widoku.

0

Pierwsza teoria jest jasna, a w drugiej chodzi Ci o coś takiego?

 adapter.addFragmenr(OstatnieWiadomosci()," <tutaj object: ValueEventListener i  onDataChange>")

o coś takiego Ci chodziło? Chyba nie... w sumie to prawie identyczne jak opcja nr1

0

Nie, chodzi o to, żeby wewnątrz fragmentu na przykład podczas onViewCreated rejestrować ValueEventListener i tam aktualizować widok.

0

no własnie dalej nie rozumiem, jak to zrobić.

w jaki sposób aktualizować tą ilość wiadomości? Jak zrobię to tak to nic się nie dzieje i cały czas wyświetla 0

  override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_glowny_widok)
  
        sprawdz = 0

        adapter.addFragmenr(OstatnieWiadomosci(),"$sprawdz powiadomień")


    fun liczenieWiadomosci{



        val ref = FirebaseDatabase.getInstance().getReference("/wiadomosci")
        ref.addListenerForSingleValueEvent(object : ValueEventListener{
            override fun onCancelled(p0: DatabaseError) {

            }

            override fun onDataChange(p0: DataSnapshot) {

                   sprawdz = p0.children.count()

            }

        })

    }


}
1

Napisałem Ci wyżej, jak to zrobić. Kod który wkleiłeś, tego nie odzwierciedla. Rejestrujesz ValueEventListener w aktywności zamiast we fragmencie.

0

Tylko, że to nie jest fragment. W tej aktywności się nie da, bo wyrzuca dużo błędów, w

wrzuciłem to tak i dalej sprawdz się nie aktualizuje. Nie wiem już jak to inaczej ma działać

class GlownyWidok : AppCompatActivity() {

    var sprawdz: Int = 0

fun lol(){


    val ref = FirebaseDatabase.getInstance().getReference("/wiadomosci")
    ref.addListenerForSingleValueEvent(object : ValueEventListener{
        override fun onCancelled(p0: DatabaseError) {

        }

        override fun onDataChange(p0: DataSnapshot) {

            val wiadomoscLiczenie = p0.getValue(wiadomosc::class.java)


            if (wiadomoscLiczenie != null){


                val iloscPostow = p0.children.count()
                sprawdz = iloscPostow

            }



        }

    })

}

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_glowny_widok)


lol()


        val cm = baseContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager


        val adapter = ViewPageAdapter(supportFragmentManager)
        adapter.addFragmenr(Wydarzenia(),"Wydarzenia")
        adapter.addFragmenr(Sciana(), "Posty")
        adapter.addFragmenr(Konto_zarzadzanie(), "Ustawienia")
        adapter.addFragmenr(topTygodnia(), "top tygodnia")
        adapter.addFragmenr(TopMiesiaca(), "top miesiaca")
        adapter.addFragmenr(OstatnieWiadomosci(),"$sprawdz powiadomień")

        viewPager.adapter = adapter
        nawigacja.setupWithViewPager(viewPager)

    }
0

Czym jest OstatnieWiadomosci()?

0

Fragmentem, ale ten kod wyżej jest normalnym AppCompatActivity standardowo generowanym przez android studio. Chodzi Ci o to, żeby ten kod wrzucić w ten fragment? wtedy nie straci możliwości aktualizacji nagłówka nawigacji?

0

Ten kod nie może być wygenerowany przez AS, bo nie ma takiej klasy w SDK czy supportowych bibliotekach jak ViewPagerAdapter. Może masz jakieś własne szablony, ale nie jest to nic domyślnie zainstalowanego z AS.

nexxx napisał(a):

Chodzi Ci o to, żeby ten kod wrzucić w ten fragment? wtedy nie straci możliwości aktualizacji nagłówka nawigacji?

A skąd ja mam to widzieć? To Twój kod. Cały czas do tej pory myślałem, że jest to element fragmentu. Skoro nim nie jest, to aktualizuj to tam, gdzie jest dostęp do tego elementu. Czyli pewnie aktywność. Jeżeli tak jak piszesz, nie ma takiej możliwości, bo nie masz dostępu do tego nagłówka, to należy samemu napisać klasę, która będzie na to pozwalać.

0

Ktoś by normalnie nakierował jak to zrobić? Pojawia się inny problem i sposób gorszy opisany w tym temacie nie może być użyty, bo crashuje apke. Prosiłbym o pomoc jak załadować dane z firebase za pomocą onDataChange i przenieść to do zewnętrznej zmiennej tak żeby mógł ją wsadzić w dowolne miejsce

0

Widzę, że Pan wyżej nie czai o co chodzi. Prosto mówiąc jak zrobić żeby zmienna która ma wartość np 3 po załadowaniu kodu została odświeżona w miejscu w którym jest wypisana?

0

Myślałem, że fora internetowe służą do pomocy początkującym a jak widać to festiwal kreowania się na znawców tematu. Zamiast pomoc jak człowiek to każdy jakieś kompleksy leczy. Myślałem, że żyjemy w czasach innych czasach a tu dalej w głowię większości potrzeba budowania ego przez klawiature. Jakby się znalazł ktoś normalny chętny pomóc to będę wdzięczny.

0

OK to dziękuję za rozwianie wątpliwości, a może mam rację tylko społeczeństwo jest pełne kompleksów, obaw i innych nieprzyjemnych czynników.
P.S bo nie wytrzymam. Kawałek kodu a niektórzy to traktują jak środek do wygrania życia. To gościu tylko kawałek kodu którego i tak nikt nie wykorzysta, a żeby Cie ucieszyć nigdy nie zarobie na nim złotówki robię to z nudów i ciekawości. Kończę rozmowę, bo z tak toksycznymi ludźmi zamknietymi w swoim ponurym świecie nie chce mieć nic wspólnego. Powinny zacząć też powstawać fora która służą do normalnej pomocy innym, a nie do budowania ego zadufanych w sobie w tym przypadku komputerowcach.

1 użytkowników online, w tym zalogowanych: 0, gości: 1