androidapp開發(fā)教程(androidapp開發(fā)入門)

  • 生活
  • 2023-04-24 13:15

在上一篇文章中,我們完成了UI界面的編寫

接下來我們就要把搜索的結(jié)果,顯示在界面上。

在Android開發(fā)中有很多種方式訪問網(wǎng)絡(luò),本次視頻將向大家介紹Retrofit,

Retrofit由Square開發(fā)的,它構(gòu)建在OkHttp之上。它是一個(gè)流行的庫,可以輕松地進(jìn)行異步網(wǎng)絡(luò)調(diào)用并將JSON數(shù)據(jù)處理為模型對(duì)象。

在Android開發(fā)中有很多種方式訪問網(wǎng)絡(luò),本次視頻將向大家介紹Retrofit,Retrofit由Square開發(fā)的,它構(gòu)建在OkHttp之上。它是一個(gè)流行的庫,可以輕松地進(jìn)行異步網(wǎng)絡(luò)調(diào)用并將JSON數(shù)據(jù)處理為模型對(duì)象。本次視頻您將了解Retrofit庫的簡(jiǎn)單實(shí)用,Moshi解析Json等知識(shí)。

在使用Retrofit之前,我們需要先在項(xiàng)目中添加Retrofit庫的依賴。編輯app/build.gradle文件,在dependencies閉包中添加如下內(nèi)容:

//retrofitimplementation"com.squareup.retrofit2:retrofit:2.9.0"//moshiimplementation("com.squareup.moshi:moshi-kotlin:1.12.0")//retrofitwithmoshiimplementation"com.squareup.retrofit2:converter-moshi:2.9.0"//coilimplementation("io.coil-kt:coil-compose:1.3.2")//kotlincoroutineimplementation"org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3"implementation"org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3"//viewmodeldeflifecycle_version="2.3.1"implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")

retrofit庫的依賴,主要負(fù)責(zé)網(wǎng)絡(luò)請(qǐng)求,允許我們發(fā)送GET,POST請(qǐng)求

moshi庫的依賴,moshi庫將幫助我們將json數(shù)據(jù)轉(zhuǎn)換為kotlin對(duì)象

converter-moshi庫,增加了對(duì)retrofit使用moshi進(jìn)行JSON解析的支持

coil庫,允許我們使用url加載網(wǎng)絡(luò)圖片,我們可以使用少量的代碼,完成圖片的加載,coil庫也是采用kotlin編寫

kotlincoroutine,我們使用kotlincoroutine的Flow處理網(wǎng)路的異步請(qǐng)求

ViewModel依賴,使用ViewModel使視圖和數(shù)據(jù)能夠分離開

完成之后我們重新編譯一下項(xiàng)目

Postman是查看API接口返回結(jié)果非常優(yōu)秀的程序,我們啟動(dòng)Postman。

使用默認(rèn)的GET***,輸入下面的URL地址https://api.map.baidu.com/weather/v1/?district_id=110100&data_type=all&ak=m5ABoErD6VuCKdyGfqoEjflYvSmn1XqR,然后單擊Send。如下圖:

在搜索結(jié)果中,將輸出類型設(shè)置為JSON。您將看到格式良好的JSON顯示:如下圖:

接下來,我們將創(chuàng)建天氣信息的數(shù)據(jù)類

數(shù)據(jù)類的創(chuàng)建,我們借助Kotlin插件,將Json字符串快速轉(zhuǎn)換為Kotlin數(shù)據(jù)類代碼

在model包下右鍵;如下圖:

點(diǎn)擊Advanced,這個(gè)支持(幾乎)各種JSON庫注釋(Gson、Jackson、Fastjson、MoShi和LoganSquare)這個(gè)我們選擇MoShi

點(diǎn)擊生成,如下圖:

這樣我們的數(shù)據(jù)類型就很方便的創(chuàng)建了。如下圖:

接下來,編寫我們的網(wǎng)絡(luò)服務(wù)

objectWeatherApiClient{privatevalBASE_URL="https://api.map.baidu.com"privatevalmoshi=Moshi.Builder().add(KotlinJsonAdapterFactory()).build()privatevalretrofit:Retrofitbylazy{Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(MoshiConverterFactory.create(moshi)).build()}valweatherApiService:WeatherApiServicebylazy{retrofit.create(WeatherApiService::class.java)}}interfaceWeatherApiService{@GET("/weather/v1/")suspendfungetWeatherData(@Query("district_id")district_id:String,@Query("data_type")data_type:String,@Query("ak")ak:String):WeatherModel}

在上面的代碼中,我們創(chuàng)建一個(gè)私有的BASE_URL變量,我們需要為moshi構(gòu)造器創(chuàng)建一個(gè)變量,添加KotlinJson的適配器工廠(KotlinJsonAdapterFactory),創(chuàng)建Retrofit,這里使用bylazy關(guān)鍵字創(chuàng)建Retrofit實(shí)例,這樣僅在需要時(shí)進(jìn)行初始化,傳入BASE_URL,添加MoshiConverterFactory轉(zhuǎn)換器工廠,然后構(gòu)建.接下來,創(chuàng)建一個(gè)接口,獲取api接口數(shù)據(jù),這里我們創(chuàng)建一個(gè)函數(shù),設(shè)置了查詢參數(shù),調(diào)用這個(gè)***就會(huì)返回查詢的數(shù)據(jù)。接下來,創(chuàng)建api接口的實(shí)例這里也是使用bylazy關(guān)鍵字創(chuàng)建延遲加載的實(shí)例,通過創(chuàng)建好的Retrofit來創(chuàng)建api接口服務(wù)。

下面創(chuàng)建Repository(數(shù)據(jù)倉庫)

classWeatherRepository{companionobject{fungetWeather(district_id:String,data_type:String,ak:String):Flow<WeatherModel>=flow{varweather=WeatherApiClient.weatherApiService.getWeatherData(district_id,data_type,ak)emit(weather)}.flowOn(Dispatchers.IO)}}

下面創(chuàng)建ViewModel

classWeatherViewModel:ViewModel(){valweatherData:MutableState<WeatherState>=mutableStateOf(WeatherState.Empty)init{getWeatherData("110100","all","m5ABoErD6VuCKdyGfqoEjflYvSmn1XqR");}fungetWeatherData(district_id:String,data_type:String,ak:String){viewModelScope.launch{WeatherRepository.getWeather(district_id,data_type,ak).onStart{weatherData.value=WeatherState.Loading}.catch{e->weatherData.value=WeatherState.Failure(e)}.collect{response->weatherData.value=WeatherState.Success(response)}}}}

在創(chuàng)建ViewModel之前,需要?jiǎng)?chuàng)建Model的狀態(tài)類

sealedclassWeatherState{classSuccess(valweather:WeatherModel):WeatherState()classFailure(valerror:Throwable):WeatherState()objectLoading:WeatherState()objectEmpty:WeatherState()}

創(chuàng)建好之后,我們?cè)贏ctivity中使用ViewModel

classMainActivity:ComponentActivity(){privatevalweatherViewModel:WeatherViewModelbyviewModels()@ExperimentalMaterialApioverridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContent{WeatherAppTheme{Surface(color=MaterialTheme.colors.background){setWeather(weatherViewModel=weatherViewModel)}}}}}

添加數(shù)據(jù)請(qǐng)求的狀態(tài),如下圖:

@ExperimentalMaterialApi@ComposablefunsetWeather(weatherViewModel:WeatherViewModel){when(valresult=weatherViewModel.weatherData.value){isWeatherState.Success->{Log.d("--result--",result.weather.toString())}isWeatherState.Failure->{Text(text="${result.error}")}isWeatherState.Loading->{Column(horizontalAlignment=Alignment.CenterHorizontally,modifier=Modifier.fillMaxSize().background(brush=Brush.verticalGradient(colors=listOf(color1,color2)))){Surface(onClick={},modifier=Modifier.fillMaxWidth(0.6f),color=Color.Transparent){Row(modifier=Modifier.padding(12.dp),verticalAlignment=Alignment.CenterVertically,horizontalArrangement=Arrangement.Center){CircularProgressIndicator(modifier=Modifier.height(16.dp).width(16.dp),strokeWidth=2.dp,color=Color.White)Spacer(modifier=Modifier.width(10.dp))ComposeText(text="加載天氣數(shù)據(jù)中...",textColor=Color.White,fontSize=16.sp)}}}}WeatherState.Empty->{}}}

在上面的代碼中,我們添加Loading,狀態(tài)的UI。

下面在WeatherState.Success狀態(tài)下,對(duì)UI界面賦值。

Column(horizontalAlignment=Alignment.CenterHorizontally,modifier=Modifier.fillMaxSize().background(brush=Brush.verticalGradient(colors=listOf(color1,color2)))){Spacer(modifier=Modifier.height(20.dp))LocationScreen(result.weather.result.location)Spacer(modifier=Modifier.height(40.dp))NowScreen(result.weather.result.now)Spacer(modifier=Modifier.height(20.dp))WeatherDaysScreen(result.weather.result.forecasts)}設(shè)置定位信息@ComposablefunLocationScreen(location:WeatherModel.Result.Location){ComposeText(text="${location.city},${location.name}",fontSize=30.sp)}

2.設(shè)置當(dāng)天天氣信息

@ComposablefunNowScreen(now:WeatherModel.Result.Now){Column(horizontalAlignment=Alignment.CenterHorizontally){valimg_url=when(now.text){"陰"->"http://www.moji.com/templets/mojichina/images/weather/weather/w2.png""雷陣雨"->"http://www.moji.com/templets/mojichina/images/weather/weather/w4.png""多云"->"http://www.moji.com/templets/mojichina/images/weather/weather/w1.png"else->"http://www.moji.com/templets/mojichina/images/weather/weather/w1.png"}Image(painter=rememberImagePainter(img_url),contentDescription="",modifier=Modifier.size(100.dp))ComposeText(text="${now.temp}°",fontSize=48.sp)}Surface(modifier=Modifier.fillMaxWidth(0.5f),color=color3,shape=RoundedCornerShape(48)){Row(horizontalArrangement=Arrangement.SpaceBetween,verticalAlignment=Alignment.CenterVertically,modifier=Modifier.fillMaxWidth().padding(8.dp)){ComposeText(text="${now.windDir}",textColor=colortext,fontSize=12.sp)ComposeText(text="${now.windClass}",textColor=colortext,fontSize=12.sp)ComposeText(text="濕度",textColor=colortext,fontSize=12.sp)ComposeText(text="${now.rh}%",textColor=colortext,fontSize=12.sp)}}}

3.設(shè)置未來5天的天氣信息

@ComposablefunWeatherDaysScreen(forecasts:List<WeatherModel.Result.Forecast>){LazyRow{items(forecasts){forecast->WeatherItems(forecast)}}}@ComposablefunWeatherItems(forecast:WeatherModel.Result.Forecast){Column(horizontalAlignment=Alignment.CenterHorizontally,modifier=Modifier.padding(start=8.dp,end=10.dp)){ComposeText(text="${forecast.week}",fontSize=16.sp)Spacer(modifier=Modifier.height(18.dp))valimg_url=when(forecast.textDay){"陰"->"http://www.moji.com/templets/mojichina/images/weather/weather/w2.png""雷陣雨"->"http://www.moji.com/templets/mojichina/images/weather/weather/w4.png""多云"->"http://www.moji.com/templets/mojichina/images/weather/weather/w1.png"else->"http://www.moji.com/templets/mojichina/images/weather/weather/w1.png"}Image(painter=rememberImagePainter(img_url),contentDescription="",modifier=Modifier.size(50.dp))Spacer(modifier=Modifier.height(2.dp))ComposeText(text="${forecast.high}°/${forecast.low}°",fontSize=22.sp)}}

猜你喜歡

主站蜘蛛池模板: 全黄大全大色全免费大片| 91免费福利精品国产| 日韩AV片无码一区二区不卡| 伊人久久大香线蕉综合电影| 97日日碰人人模人人澡| 天天综合天天做天天综合| 久久精品国产亚洲AV麻豆王友容| 狠狠躁夜夜躁人人爽天天天天97 | 热re99久久精品国99热| 国产做国产爱免费视频| 69国产精品视频免费| 孩交精品xxxx视频视频| 久久国产精品波多野结衣AV| 欧美日韩在线一区二区三区| 动漫女同性被吸乳羞羞漫画| 高龄五十路中出| 国产精品成人扳**a毛片| 亚洲欧美日韩人成在线播放| 自拍偷自拍亚洲精品被多人伦好爽| 好朋友4韩国完整版观看| 久久午夜无码鲁丝片| 欧美亚洲桃花综合| 人妻少妇精品视频一区二区三区 | 新梅瓶1一5集在线观看| 亚洲va欧美va天堂v国产综合 | 五十路亲子中出在线观看| 毛茸茸性XXXX毛茸茸毛茸茸| 军人野外吮她的花蒂无码视频| 黄色a级片免费看| 国产精品区一区二区三在线播放| 丰满爆乳无码一区二区三区| 最近最新最好的2018中文字幕| 亚洲欧美成人一区二区三区| 精品一区二区三区av天堂| 国产一区二区三区精品视频| 成人羞羞视频国产| 国产精品理论电影| 99ri精品国产亚洲| 女人是男人未来1分50秒| 中文字幕avdvd| 日日夜夜天天干|