簡體   English   中英

嘗試使用Android Studio在Kotlin中的Retrofit中解析JSON時獲取空指針異常

[英]Getting null pointer exception when trying to parse JSON in Retrofit in kotlin with Android studio

我正在嘗試從Github API獲取用戶。 API運作良好,並且收到響應,但是在嘗試解析JSON時遇到問題。 請指導我。 我對Kotlin和Retrofit很滿意。 因此,請指導我如何獲得適當的解決方案。 這是我的JSON響應。

    {
    "login": "photoionized",
    "id": 597302,
    "node_id": "MDQ6VXNlcjU5NzMwMg==",
    "avatar_url": "https://avatars0.githubusercontent.com/u/597302?v=4",
    "gravatar_id": "",
    "url": "https://api.github.com/users/photoionized",
    "html_url": "https://github.com/photoionized",
    "followers_url": "https://api.github.com/users/photoionized/followers",
    "following_url": "https://api.github.com/users/photoionized/following{/other_user}",
    "gists_url": "https://api.github.com/users/photoionized/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/photoionized/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/photoionized/subscriptions",
    "organizations_url": "https://api.github.com/users/photoionized/orgs",
    "repos_url": "https://api.github.com/users/photoionized/repos",
    "events_url": "https://api.github.com/users/photoionized/events{/privacy}",
    "received_events_url": "https://api.github.com/users/photoionized/received_events",
    "type": "User",
    "site_admin": false,
    "name": "Andrew Stucki",
    "company": "Aspera, Inc.",
    "blog": "",
    "location": "Alameda, CA",
    "email": null,
    "hireable": null,
    "bio": null,
    "public_repos": 4,
    "public_gists": 1,
    "followers": 2,
    "following": 0,
    "created_at": "2011-02-02T18:44:31Z",
    "updated_at": "2016-05-12T04:40:54Z"
}

這是MyApi代碼

    interface MyApi {
    @GET("users/{username}")
    suspend fun userLogin(
        @Path("username") username: String

    ) : Response<AuthResponse>

    companion object{
        operator fun invoke() : MyApi {
            return Retrofit.Builder()
                .baseUrl("https://api.github.com")
                .addConverterFactory(GsonConverterFactory.create())
                .build()
                .create(MyApi :: class.java)
        }
    }
}

這是我的POKO課

const val CURRENT_USER_ID = 0

@Entity
data class User (
    var id: Int? = null,
    var name: String? = null,
    var email: String? = null,
    var login: String? = null,
    var avatar_url: String? = null,
    var gravatar_id: String? = null,
    var url: String? = null,
    var html_url: String? = null,
    var company: String? = null,
    var followers_url: String? = null,
    var created_at: String? = null,
    var updated_at: String? = null
){
    @PrimaryKey(autoGenerate = false)
    var uid: Int = CURRENT_USER_ID
}

這是用戶存儲庫類代碼

   class UserRepository {

    suspend fun userLogin(username: String) : Response<AuthResponse>{
    return MyApi().userLogin(username)

    }
}

這是驗證響應

data class AuthResponse (
    val isSuccessful : Boolean?,
    val message: String?,
    val user: User?
)

here is AuthViewModel

    class AuthViewModel : ViewModel() {
    var username: String? = null

    var authListener : AuthListener? = null

    fun onLoginButtonClick(view: View){
        authListener?.onStarted()
        if (username.isNullOrEmpty()){
            authListener?.onFailure("Invalid email or password")
            //
            return
        }
        Coroutines.main{
            val response = UserRepository().userLogin(username!!)
            if (response.isSuccessful){
                authListener?.onSuccess(response.body()?.user!!)

            }else{
                authListener?.onFailure("Error Code: ${response.code()}")
            }
        }

    }
}

這是登錄活動

class LoginActivity : AppCompatActivity(), AuthListener {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding : ActivityLoginBinding = DataBindingUtil.setContentView(this, R.layout.activity_login)
        val viewModel = ViewModelProviders.of(this).get(AuthViewModel :: class.java)
        binding.viewmodel= viewModel
        viewModel.authListener = this
    }
    override fun onStarted() {
        toast("Login Started")
        progress_bar.show()
    }

    override fun onSuccess(user: User) {
        progress_bar.hide()
        toast("${user.login} is found")
    }
    override fun onFailure(message: String) {
        progress_bar.hide()
        toast(message)
    }
}

這是我的Logcat錯誤

PID:15204

com.isofttechpro.myapplication.ui.auth.AuthViewModel $ onLoginButtonClick $ 1.invokeSuspend(AuthViewModel.kt:23)的kotlin.KotlinNullPointerException

當您使用!!強制解開null值時,會發生KotlinNullPointerException !! 錯誤可能在於以下幾行,

val response = UserRepository().userLogin(username!!)
if (response.isSuccessful){
  authListener?.onSuccess(response.body()?.user!!)

盡量不要使用!! 盡可能嘗試使用letapplyrun等。例如,

//rather than
//authListener?.onSuccess(response.body()?.user!!)
//use
response.body()?.user?.let {
  authListener?.onSuccess(it)
}

另一種替代方法是使用elvis運算符並提供默認值。 例如,

authListener?.onSuccess(response.body()?.user?:"default value")

首先,不要使用null來初始化您的數據類屬性。

其次,您的響應使用原始JSON,因此不需要任何父類進行解析。 例如,不需要您的數據類AuthResponse

使用以下代碼將其解析為您的數據模型。

val gson:Gson = Gson()
var user = gson?.fromJson(response.body(), Users::class.java)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM