NIe moge przejsc do nastepnego activity. Blad

Odpowiedz Nowy wątek
2020-02-29 18:11

Rejestracja: 7 miesięcy temu

Ostatnio: 4 tygodnie temu

0

Cześc,

Gdy probuje przejsc do nastepnego activity dostaje ponizszy blad:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference

Wiecie moze co moze go powodowac? Przegladalem wiele stron i nie mam pojecia o co chodzi. Nigdy wczesniej takiego bledu nie mialem i nie bardzo jestem w stanie ruszyc dalej :D

Kod zrodlowy:

class ApiConnection {

    var baseApiURl = "http://localhost:8081"
    var data = arrayListOf<User>()

    fun connectApi(): ApiService {
        val retrofit = Retrofit.Builder()
            .baseUrl(baseApiURl)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
        return retrofit.create(ApiService::class.java)
    }

    fun loginRequest(
        login: String,
        password: String
    ){
        val service = connectApi()
        val call = service.login(login, password)
        call.enqueue(object: Callback<UserResponse> {
            override fun onFailure(call: Call<UserResponse>?, t: Throwable?) {
                Log.v("retrofit", "call failed")
            }
            override fun onResponse(call: Call<UserResponse>?, response: Response<UserResponse>?) {
                addDataToList(response)
            }

        })
    }

    fun addDataToList(response: Response<UserResponse>?) {
        var mainActivity = MainActivity()
        data.add(
            User(
                response!!.body()!!.idUser,
                response!!.body()!!.login,
                response!!.body()!!.password,
                response!!.body()!!.name,
                response!!.body()!!.surname,
                response!!.body()!!.lastLogin
            )
        )

        mainActivity.loginIntoServer(data)
    }
}
class MainActivity : AppCompatActivity() {

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

        val api = ApiConnection()

        button_checkIfThisAccountExit_mainActivity.setOnClickListener {
            api.loginRequest(editText_login_activityMain.text.toString(), editText_password_mainActivity.text.toString())
        }
    }

    fun loginIntoServer(data: ArrayList<User>) {
        val context = this
        val intent = Intent(context, Main2Activity::class.java)
        startActivity(intent)
    }
}

Pozostało 580 znaków

2020-02-29 18:23

Rejestracja: 2 lata temu

Ostatnio: 5 godzin temu

0

Przede wszystkim czegoś takiego się nie robi var mainActivity = MainActivity(). Nigdy nie powinieneś tworzyć aktywności (i większości komponentów frameworka) samemu poprzez konstruktor. Za to odpowiada Android. Twój problem wynika pośrednio z tego.

W jaki poprawny sposob powienien odwolac sie do innej klasy? - Szymon Markowski 2020-02-29 18:24
Jakiej innej klasy? I nie odpisuj na rzeczy związane z tematem w komentarzach, bo to wprowadza zamieszanie. - Michał Sikora 2020-02-29 18:25

Pozostało 580 znaków

2020-02-29 18:27

Rejestracja: 7 miesięcy temu

Ostatnio: 4 tygodnie temu

0

W jaki sposób powinienem odwołać się do jakiejś funkcji, która znajduje się w innej klasie. Na moim przykladzie jak z klasy "ApiConnection" odwołać się do funkcji będącej w klasie "MainActivity"

Pozostało 580 znaków

2020-02-29 18:37

Rejestracja: 2 lata temu

Ostatnio: 5 godzin temu

0

Możesz się odwołać do metody obiektu (nie klasy), która jest zdefiniowana w klasie. Wystarczy przekazać obiekt tej klasy tam, gdzie chcesz wywołać tę metodę. Aczkolwiek w tym wypadku to kiepskie rozwiązanie. Powinieneś przekazywać callback do metody w ApiConnection. Czyli coś w tym stylu.

class ApiConnection {
  fun loginRequest(login: String, password: String, callback: Callback<UserResponse>): Call<UserResponse> {
    val call = service.login(login, password)
    call.enqueue(callback)
    return call
  }
}

class MainActivity {
  override fun onCreate(inState: Bundle?) {
    super.onCreate(inState)
    setContentView(R.layout.activity_main)

    val api = ApiConnection()

    button_checkIfThisAccountExit_mainActivity.setOnClickListener {
      val callback = TODO()
      api.loginRequest(editText_login_activityMain.text.toString(), editText_password_mainActivity.text.toString(), callback)
    }
  }
}

I tak jest tu sporo niepoprawnych rzeczy, ale powinno Ci pozwolić ruszyć z miejsca.

Pozostało 580 znaków

2020-03-01 09:37

Rejestracja: 7 miesięcy temu

Ostatnio: 4 tygodnie temu

0

O jakich niepoprawnych rzeczach masz na mysli ? Chciałbym od początku już nabyć nawyk pisania tak jak powinno to wygladac, a nie tylko tak zeby kod dzialal.

Pozostało 580 znaków

2020-03-01 09:56

Rejestracja: 2 lata temu

Ostatnio: 5 godzin temu

0
  1. Nie obsługujesz nigdzie błędów HTTP. Zakładasz, że response zawsze zwróci kod 200 i nie sprawdzasz sytuacji innych możliwości takich jak np. 404 czy 500.
  2. Nie anulujesz nigdzie operacji w tle w przypadku śmierci aktywności. Może dojść do wycieków pamięci i awarii aplikacji przez to, że nie anulujesz operacji logowania ze względu na cykl życia aplikacji.
  3. Nie korzystasz nigdzie z przekazywania zależności. Aktywność nie powinna tworzyć takie obiektu jak ApiConnection tylko go dostawać z zewnątrz. Na Androidzie to jest problematyczne, ale możesz poczytać o takich rzeczach jak Dependency Injection. Tak samo ApiConnection nie powinno tworzyć ApiService tylko dostawać go z zewnątrz. Tak naprawdę cały ta klasa ApiConnection nie jest w ogóle potrzebna w tym momencie, bo nic nie robi.
  4. Przy każdej próbie logowania tworzysz nowy obiekt Retrofit i za jego pomocą nowy obiekt ApiService. Jest to bardzo niewydajne i bardzo kosztowne ze względu na to jak działa Retrofit. Powinno się to dziać raz przy starcie aplikacji.
  5. Złe użycie nulli. Argumenty metody w Callback nigdy nie będą nullami. body() w response() już może być nullem, ale to podchodzi pod pierwszą uwagę.
  6. Możliwe, że było to tylko na potrzeby debugowania, ale obiekt w stylu var data = arrayListOf<User>() jest kiepskim pomysłem, jeśli chcesz w ten sposób przechowywać dane użytkowników. O ile może Cię nie interesować zapis danych pomiędzy włączeniem i wyłączeniem aplikacji, o tyle nawet ulotne dane powinny przetrwać przynajmniej zmianę konfiguracji aplikacji, a jeszcze lepiej jakby przetrwały śmierć procesu aplikacji.
edytowany 1x, ostatnio: Michał Sikora, 2020-03-01 09:56

Pozostało 580 znaków

Odpowiedz

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