当前位置: 首页 > news >正文

官方网站开发广州专门做seo的公司

官方网站开发,广州专门做seo的公司,服务好的丹阳网站建设,福州商城网站开发公司在Android笔记(二十二):Paging3分页加载库结合Compose的实现网络单一数据源访问一文中,实现了单一数据源的访问。在实际运行中,往往希望不是单纯地访问网络数据,更希望将访问的网络数据保存到移动终端的SQL…

在Android笔记(二十二):Paging3分页加载库结合Compose的实现网络单一数据源访问一文中,实现了单一数据源的访问。在实际运行中,往往希望不是单纯地访问网络数据,更希望将访问的网络数据保存到移动终端的SQLite数据库中,使得移动应用在离线的状态下也可以从数据库中获取数据进行访问。在本笔记中,将讨论多层次数据的访问,即结合网络资源+本地SQLite数据库中的数据的处理。在本笔记中,仍然采用Android笔记(二十二)中的网络资源:
在这里插入图片描述
上列展示的json数组包含了多个json对象,每个json对象的格式类似下列形式:

{"actors":"演员",
"directors":"导演",
"intro":"电影简介",
"poster":"http://localhost:5000/photo/s_ratio_poster/public/p2626067725.jpg",
"region":"地区",
"release":"发布年份",
"trailer_url":"https://localhost:5000/trailer/268661/#content",
"video_url":"https://localhost:5000/d04d3c0d2132a29410dceaeefa97e725/view/movie/M/402680661.mp4"}

一、分层次访问数据的架构

在这里插入图片描述
与单一数据源结构不同在于增加了RemoteMediator。当应用的已缓存数据用尽时,RemoteMediator 会充当来自 Paging 库的信号。可以使用此信号从网络加载更多数据并将其存储在本地数据库中,PagingSource 可以从本地数据库加载这些数据并将其提供给界面进行显示。
当需要更多数据时,Paging 库从 RemoteMediator 实现调用 load() 方法。这是一项挂起功能,因此可以放心地执行长时间运行的工作。此功能通常从网络源提取新数据并将其保存到本地存储空间。
此过程会处理新数据,但长期存储在数据库中的数据需要进行失效处理(例如,当用户手动触发刷新时)。这由传递到 load() 方法的 LoadType 属性表示。LoadType 会通知 RemoteMediator 是需要刷新现有数据,还是提取需要附加或前置到现有列表的更多数据。
通过这种方式,RemoteMediator 可确保应用以适当的顺序加载用户要查看的数据。

二、定义实体类

1.定义Film类

@Entity(tableName="films")
data class Film(@PrimaryKey(autoGenerate = false)@SerializedName("name")val name:String,@SerializedName("release")val release:String,@SerializedName("region")val region:String,@SerializedName("directors")val directors:String,@SerializedName("actors")val actors:String,@SerializedName("intro")val intro:String,@SerializedName("poster")val poster:String,@SerializedName("trailer_url")val trailer:String,@SerializedName("video_url")val video:String
)

在上述代码中,将Film类映射为数据库中的数据表films。对应的数据表结构如下所示:

在这里插入图片描述

2.定义FilmRemoteKey类

因为从网络访问每一个条电影记录需要知道记录的上一页和下一页的内容,因此定义FilmRemoteKey类,代码如下:

@Entity(tableName = "filmRemoteKeys")
data class FilmRemoteKey(@PrimaryKey(autoGenerate = false)val name:String,val prePage:Int?,val nextPage:Int?
)

FilmRemoteKey对应的数据表结构如下:
在这里插入图片描述
name表示电影名,也是关键字
prePage表示记录的上一页的页码,因为第一页的所有记录没有上一页,因此,前5条记录的prePage均为空
nextPage表示记录的下一页的页面。

三、定义网络访问

1.网络访问服务接口

interface FilmApi {@GET("film.json")suspend fun getData(@Query("page") page:Int,@Query("size") size:Int):List<Film>
}

2.Retrofit构建网络服务

object RetrofitBuilder {private const val  BASE_URL = "http://10.0.2.2:5000/"private fun getRetrofit(): Retrofit {return Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build()}val apiService:FilmApi = getRetrofit().create(FilmApi::class.java)
}

四、定义数据库的访问

1.电影数据访问对象的接口

@Dao
interface FilmDao {/*** 插入数据列表* @param  films List<Film>*/@Insert(onConflict = OnConflictStrategy.REPLACE)suspend fun insertAll(films: List<Film>)/*** 检索所有的Film记录* @return PagingSource<Int, Film>*/@Query("select * from films")fun queryAll(): PagingSource<Int, Film>/*** Delete all* 删除表films中所有记录*/@Query("DELETE FROM films")suspend fun deleteAll()
}

2.电影页码数据访问对象的接口

@Dao
interface FilmRemoteKeyDao {@Query("SELECT * FROM filmRemoteKeys WHERE name = :name")suspend fun findByName(name:String):FilmRemoteKey@Insert(onConflict =OnConflictStrategy.REPLACE)suspend fun insertAllKeys(remoteKeys:List<FilmRemoteKey>)@Query("DELETE FROM filmRemoteKeys")suspend fun deleteAllKeys()
}

3.创建数据库

@Database(entities = [Film::class,FilmRemoteKey::class], version = 1)
abstract class FilmDatabase : RoomDatabase() {abstract fun filmDao(): FilmDaoabstract fun filmRemoteKeyDao():FilmRemoteKeyDaocompanion object{private var instance: FilmDatabase? = null/*** 单例模式创建为一个FilmDB对象实例*/@Synchronizedfun getInstance(context:Context = FilmApp.context): FilmDatabase {instance?.let{return it}return Room.databaseBuilder(context,FilmDatabase::class.java,"filmDB.db").build()}}
}

五、定义代码层

1.定义RemoteMediator类

@OptIn(ExperimentalPagingApi::class)
class FilmRemoteMediator(private val database:FilmDatabase,private val networkService:FilmApi
) : RemoteMediator<Int, Film>() {private val filmDao = database.filmDao()private val filmRemoteKeyDao = database.filmRemoteKeyDao()override suspend fun load(loadType: LoadType,state: PagingState<Int, Film>): MediatorResult {return try{/***  从数据库获取缓存的当前页面*/val currentPage:Int = when(loadType){//UI初始化刷新LoadType.REFRESH-> {val remoteKey:FilmRemoteKey? = getRemoteKeyToCurrentPosition(state)remoteKey?.nextPage?.minus(1)?:1}//在当前列表头添加数据使用LoadType.PREPEND-> {val remoteKey = getRemoteKeyForTop(state)val prevPage = remoteKey?.prePage?:return MediatorResult.Success(remoteKey!=null)prevPage}//尾部加载更多的记录LoadType.APPEND->{val remoteKey = getRemoteKeyForTail(state)val nextPage = remoteKey?.nextPage?:return MediatorResult.Success(remoteKey!=null)nextPage}}/*** 联网状态下的处理* 获取网络资源* response*/val response = networkService.getData(currentPage,5)val endOfPaginationReached = response.isEmpty()val prePage = if(currentPage == 1) null else currentPage-1val nextPage = if(endOfPaginationReached) null else currentPage+1database.withTransaction{//刷新记录,需要删除原有的记录if(loadType == LoadType.REFRESH){filmDao.deleteAll()filmRemoteKeyDao.deleteAllKeys()}//获取的记录映射成对应的索引记录val keys:List<FilmRemoteKey> = response.map{film:Film->FilmRemoteKey(film.name,prePage,nextPage)}filmRemoteKeyDao.insertAllKeys(keys)filmDao.insertAll(response)}MediatorResult.Success(endOfPaginationReached)}catch(e:IOException){MediatorResult.Error(e)}catch(e:HttpException){MediatorResult.Error(e)}}/*** 获取当前位置对应的FilmRemoteKey* @param state PagingState<Int, Film>* @return FilmRemoteKey?*/private suspend fun getRemoteKeyToCurrentPosition(state:PagingState<Int,Film>):FilmRemoteKey?=state.anchorPosition?.let{position:Int->state.closestItemToPosition(position)?.name?.let{name:String->filmRemoteKeyDao.findByName(name)}}/*** 获取当前页面从头部第一个位置对应的FilmRemoteKey* @param state PagingState<Int, Film>* @return FilmRemoteKey?*/private suspend fun getRemoteKeyForTop(state:PagingState<Int,Film>):FilmRemoteKey?=state.pages.firstOrNull{ it:PagingSource.LoadResult.Page<Int,Film>->it.data.isNotEmpty()}?.data?.firstOrNull()?.let{film:Film->filmRemoteKeyDao.findByName(film.name)}/*** 获取当前尾部最后一个位置对应的FilmRemoteKey* @param state PagingState<Int, Film>* @return FilmRemoteKey?*/private suspend fun getRemoteKeyForTail(state:PagingState<Int,Film>):FilmRemoteKey?=state.pages.lastOrNull{it:PagingSource.LoadResult.Page<Int,Film>->it.data.isNotEmpty()}?.data?.lastOrNull()?.let{film:Film->filmRemoteKeyDao.findByName(film.name)}
}

2.定义PagingSource数据源

@ExperimentalPagingApi
class FilmRepository(private val filmApi:FilmApi,private val filmDatabase:FilmDatabase
) {fun getAllFilms(): Flow<PagingData<Film>> {val pagingSourceFactory:()->PagingSource<Int, Film> = {filmDatabase.filmDao().queryAll()}return Pager(config = PagingConfig(pageSize = 5),initialKey = null,remoteMediator = FilmRemoteMediator(filmDatabase,filmApi),pagingSourceFactory = pagingSourceFactory).flow}
}

六、定义视图模型层

@OptIn(ExperimentalPagingApi::class)
class MainViewModel(): ViewModel() {val filmRepository:FilmRepository = FilmRepository(RetrofitBuilder.apiService,FilmDatabase.getInstance())fun getFilms()=filmRepository.getAllFilms()
}

七、定义界面层

1.单独电影界面的定义

@Composable
fun FilmCard(film: Film?) {Card(modifier = Modifier.fillMaxSize().padding(2.dp),elevation = CardDefaults.cardElevation(5.dp),colors = CardDefaults.cardColors(containerColor = Color.DarkGray)){Column{Row(modifier = Modifier.fillMaxSize()){AsyncImage(modifier=Modifier.width(180.dp).height(240.dp),model = "${film?.poster}",contentDescription = "${film?.name}")Column{Text("${film?.name}",fontSize = 18.sp,color = Color.Green)Text("导演:${film?.directors}",fontSize = 14.sp,color = Color.White)Text("演员:${film?.actors}", fontSize = 14.sp,color = Color.Green)}}Text("${film?.intro?.subSequence(0,60)} ...",fontSize = 14.sp,color= Color.White)Row(horizontalArrangement = Arrangement.End,modifier = Modifier.fillMaxSize()){Text("More",fontSize=12.sp)IconButton(onClick ={}){Icon(imageVector = Icons.Default.MoreVert,tint= Color.Green,contentDescription = "更多...")}}}}
}

2.定义电影列表

@Composable
fun FilmScreen(mainViewmodel:MainViewModel){val films = mainViewmodel.getFilms().collectAsLazyPagingItems()Column(horizontalAlignment = Alignment.CenterHorizontally,modifier = Modifier.background(Color.White)){LazyColumn{items(films.itemCount){FilmCard(films[it])}}}
}

八、定义主活动MainActivity

class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {val mainViewModel:MainViewModel = viewModel()Ch11_DemoTheme {// A surface container using the 'background' color from the themeSurface(modifier = Modifier.fillMaxSize(),color = MaterialTheme.colorScheme.background) {FilmScreen(mainViewmodel = mainViewModel)}}}}
}

参考文献

Paging库概览
https://developer.android.google.cn/topic/libraries/architecture/paging/v3-overview?hl=zh-cn


文章转载自:
http://dinncosherris.ssfq.cn
http://dinncomidway.ssfq.cn
http://dinncotriweekly.ssfq.cn
http://dinncopetiolate.ssfq.cn
http://dinncocrumblings.ssfq.cn
http://dinncomicrobe.ssfq.cn
http://dinncojujutsu.ssfq.cn
http://dinncofrat.ssfq.cn
http://dinncoagatha.ssfq.cn
http://dinncoliposoluble.ssfq.cn
http://dinncocullet.ssfq.cn
http://dinncobenighted.ssfq.cn
http://dinncosmorzando.ssfq.cn
http://dinncosporiferous.ssfq.cn
http://dinncocabala.ssfq.cn
http://dinncoteenster.ssfq.cn
http://dinncorushee.ssfq.cn
http://dinncoconflate.ssfq.cn
http://dinncofilipine.ssfq.cn
http://dinncoastonish.ssfq.cn
http://dinncovolleyball.ssfq.cn
http://dinncoperiodically.ssfq.cn
http://dinnconard.ssfq.cn
http://dinncochechako.ssfq.cn
http://dinncounfitting.ssfq.cn
http://dinncobiogeocoenosis.ssfq.cn
http://dinncoconfabulation.ssfq.cn
http://dinncochassid.ssfq.cn
http://dinncopleasure.ssfq.cn
http://dinncoentasia.ssfq.cn
http://dinncoindustrious.ssfq.cn
http://dinncolown.ssfq.cn
http://dinncoprincipe.ssfq.cn
http://dinnconachas.ssfq.cn
http://dinncoparacystitis.ssfq.cn
http://dinncoletting.ssfq.cn
http://dinncoregan.ssfq.cn
http://dinncolunik.ssfq.cn
http://dinncoexaminationism.ssfq.cn
http://dinncocommandant.ssfq.cn
http://dinncoexhaust.ssfq.cn
http://dinncowps.ssfq.cn
http://dinncophylogenetic.ssfq.cn
http://dinncomoneywort.ssfq.cn
http://dinncoomenta.ssfq.cn
http://dinncoetcher.ssfq.cn
http://dinncochitin.ssfq.cn
http://dinncostrafe.ssfq.cn
http://dinncorhythmize.ssfq.cn
http://dinncofinish.ssfq.cn
http://dinncodiaphragmatic.ssfq.cn
http://dinncosecund.ssfq.cn
http://dinncoyellowhead.ssfq.cn
http://dinncogeometrid.ssfq.cn
http://dinncopiddling.ssfq.cn
http://dinncomanually.ssfq.cn
http://dinncoopenness.ssfq.cn
http://dinncochatter.ssfq.cn
http://dinncorestrictionism.ssfq.cn
http://dinncoscepticize.ssfq.cn
http://dinncodesna.ssfq.cn
http://dinncobinit.ssfq.cn
http://dinncoavon.ssfq.cn
http://dinncohurricoon.ssfq.cn
http://dinncogravelstone.ssfq.cn
http://dinncocompendia.ssfq.cn
http://dinncoreedify.ssfq.cn
http://dinncorhytidectomy.ssfq.cn
http://dinncooption.ssfq.cn
http://dinncooutwell.ssfq.cn
http://dinncohornlessness.ssfq.cn
http://dinncotransitional.ssfq.cn
http://dinncoshrew.ssfq.cn
http://dinncotripos.ssfq.cn
http://dinncoinsuperability.ssfq.cn
http://dinncokielbasa.ssfq.cn
http://dinncoiced.ssfq.cn
http://dinncomelanesia.ssfq.cn
http://dinncofortress.ssfq.cn
http://dinncolahar.ssfq.cn
http://dinncoblinding.ssfq.cn
http://dinncomutable.ssfq.cn
http://dinncoanimalism.ssfq.cn
http://dinncotearjerker.ssfq.cn
http://dinncomatelot.ssfq.cn
http://dinncohowtowdie.ssfq.cn
http://dinncoeditorialise.ssfq.cn
http://dinncolay.ssfq.cn
http://dinncoboilover.ssfq.cn
http://dinncolaccolith.ssfq.cn
http://dinncoathymic.ssfq.cn
http://dinncopm.ssfq.cn
http://dinncosierra.ssfq.cn
http://dinncopianola.ssfq.cn
http://dinncostridence.ssfq.cn
http://dinncolycanthropy.ssfq.cn
http://dinncounarm.ssfq.cn
http://dinncoantiobscenity.ssfq.cn
http://dinncoaltar.ssfq.cn
http://dinncogenesic.ssfq.cn
http://www.dinnco.com/news/117291.html

相关文章:

  • 广州公司网站开发厦门网站外包
  • 网站开发实训意义品牌营销做得好的品牌有哪些
  • 建设团队网站长沙做网络推广公司的
  • app是什么意思seo深度解析
  • 吉林市网站建设优化设计答案四年级上册语文
  • 做渔船的网站深圳网络推广哪家好
  • 一个网站价格seo网站排名优化快速排
  • php和mysql web做网站如何优化关键词
  • 做英文色情网站犯法吗seo免费培训教程
  • 个人简历表模板电子版上海牛巨微seo优化
  • 三水网站开发关键词优化多少钱
  • 二级域名网站济南seo怎么优化
  • 网站可以做什么深圳百度推广开户
  • 建设网站的意义百度seo网站优化
  • 网站做支付宝支付接口推广神器app
  • 网站开发跟app开发的差别综合性b2b电子商务平台网站
  • 深圳市营销型网站如何给网站做推广
  • 网站建设先进材料做外贸怎么推广
  • 网站建设全套教程市场seo是什么
  • 公司要招个做网站的人北京网讯百度科技有限公司
  • 南充做网站略奥网络推蛙网络
  • 深圳做h5网站如何注册一个网站
  • 网站开发常见面试如何对一个网站进行seo
  • 全网网络营销推广火热招商中罗湖区seo排名
  • 自己做一元购网站网站备案查询工信部
  • 宁波建网站方式网站注册流程
  • abc公司电子商务网站建设策划书优化排名 生客seo
  • 网站规划的类型百度竞价运营
  • wordpress 访问限制seo对网店推广的作用有哪些
  • 大唐集团电子商务平台网站性能优化的方法有哪些