Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

请教 #6

Open
qtybpg opened this issue Jun 27, 2019 · 42 comments
Open

请教 #6

qtybpg opened this issue Jun 27, 2019 · 42 comments

Comments

@qtybpg
Copy link

qtybpg commented Jun 27, 2019

大佬,你定义了一个bindadapter toast,在xml中也使用了,可是该如何通过触发它呢?

@qtybpg
Copy link
Author

qtybpg commented Jun 27, 2019

大佬,我突然想到,在你的paoactivity中将调用dispatchFailure改为mViewModel.error.set(it),可以触发。我这种写法正确吗?

@ditclear
Copy link
Owner

ditclear commented Jun 27, 2019 via email

@qtybpg
Copy link
Author

qtybpg commented Jun 27, 2019

好的,主要是我现在处于初学mvvm的状态,toast中传的this也是可以视为在view层传入的吗?之前一直在用mvc,弄的我现在有点懵了。

@ditclear
Copy link
Owner

ditclear commented Jun 27, 2019 via email

@qtybpg
Copy link
Author

qtybpg commented Jun 27, 2019

好的,大佬,之前mvc开发总是view层和model层混在一起,让我都懵了。

@ditclear
Copy link
Owner

ditclear commented Jun 27, 2019

不太清楚的话,可以先看看 专栏 https://xiaozhuanlan.com/topic/7590648312

@qtybpg
Copy link
Author

qtybpg commented Jun 28, 2019

大佬,我目前正在参照你的项目写demo,看了你的前三篇后,有个疑问,你数据库的applicationcontext是自己新建了一个类继承了application吗?从而获得了applicationcontext。

@qtybpg
Copy link
Author

qtybpg commented Jun 28, 2019

并且这个applicatoncontext是个全局变量

@ditclear
Copy link
Owner

一般来说是这样的,使用Koin之后,可以通过androidApplication()方法获取到,在PaoApp.kt里startKoin的时候就赋值了

@qtybpg
Copy link
Author

qtybpg commented Jun 28, 2019

的确,我看到了koin,也猜到是这种,不过我想试试不用依赖注入的组件。

@qtybpg
Copy link
Author

qtybpg commented Jul 1, 2019

fun getWeather()=local.getArticleById(8773).onErrorResumeNext(
// Log.e("weather","no localweather")
remote.getArticleById(8773)
.doOnSuccess {
Log.e("weather",it.content)
local.insertArticle(it)
}.doOnError{
Log.e("weather",it.message)
}.doFinally {
Log.e("weather","final")

        }
)

大佬,我使用了你获得数据的api和同样的bean,可是并没有走doOn系列的方法。您能告诉我问题出现在哪吗?因为连log都没

@qtybpg
Copy link
Author

qtybpg commented Jul 1, 2019

val remote= Retrofit.Builder()
.baseUrl("http://api.jcodecraeer.com/")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(WeatherService::class.java)
val local =TestDataBase.getInstance(getAppConText()).getArticalDao();

val weatherRepo=WeatherRepo(remote,local);

fun getWeather(){
weatherRepo.getWeather()
    .async(1000)
    .doOnSuccess { result:Article->
        result.let {
            weatherdara.set(it.content)

        }
    }

@ditclear
Copy link
Owner

ditclear commented Jul 1, 2019

你没有订阅

val weatherRepo=WeatherRepo(remote,local);

fun getWeather(){
weatherRepo.getWeather()
    .async(1000)
    .doOnSuccess { result:Article->
        result.let {
            weatherdara.set(it.content)

        }
    }.subscribe({},{})

@qtybpg
Copy link
Author

qtybpg commented Jul 1, 2019

嗯,好的,谢谢大佬。

@qtybpg
Copy link
Author

qtybpg commented Jul 1, 2019

大佬,当我打算插入新数据时,attempt to re-open an already-closed object: SQLiteDatabase:编译器给我推送了这个异常,网上搜到的都和我的情况不太相似。
abstract fun getPersonDao():PersonDao
abstract fun getWeatherDao():WeatherDao
abstract fun getArticalDao():PaoDao
companion object {

    @Volatile private var INSTANCE: TestDataBase? = null

    fun getInstance(context: Context): TestDataBase =
        INSTANCE ?: synchronized(this) {
            INSTANCE ?: buildDatabase(context).also { INSTANCE = it }
        }

    private fun buildDatabase(context: Context) =
        Room.databaseBuilder(context.applicationContext,
            TestDataBase::class.java, "Test.db")
            .build()
}

@qtybpg
Copy link
Author

qtybpg commented Jul 1, 2019

emmm,我卸载了以后再试就好使了,是因为我修改了我数据Bean的构造方法吗?导致表的结构对不上?

@qtybpg
Copy link
Author

qtybpg commented Jul 12, 2019

大佬,当我使用room数据库,想在表中插入list类型的数据时,按照网上的文档出现了错误
class CityAndWeather{

@Embedded
public var weather:Weather?=null

@Relation(parentColumn = "id",entityColumn = "cityId",entity = WeatherData::class)
public var data:List<WeatherData>?=null;

}

@entity(tableName = "weather")
class Weather{
@PrimaryKey
@ColumnInfo(name = "id")
@nonnull
private var cityid: String?=null
@ColumnInfo(name = "updatetime")
private var update_time: String? = null
@ColumnInfo(name = "city")
private var city: String? = null
@ColumnInfo(name = "city_En")
private var cityEn: String? = null
@ColumnInfo(name = "country")
private var country: String? = null
@ColumnInfo(name = "country_En")
private var countryEn: String? = null

fun getCityid(): String? {
    return cityid
}

fun setCityid(cityid: String) {
    this.cityid = cityid
}

fun getUpdate_time(): String? {
    return update_time
}

fun setUpdate_time(update_time: String) {
    this.update_time = update_time
}

fun getCity(): String? {
    return city
}

fun setCity(city: String) {
    this.city = city
}

fun getCityEn(): String? {
    return cityEn
}

fun setCityEn(cityEn: String) {
    this.cityEn = cityEn
}

fun getCountry(): String? {
    return country
}

fun setCountry(country: String) {
    this.country = country
}

fun getCountryEn(): String? {
    return countryEn
}

fun setCountryEn(countryEn: String) {
    this.countryEn = countryEn
}

}

@entity
class WeatherData{
@PrimaryKey
@ColumnInfo(name = "day")
@nonnull
private var day: String?=null
@ColumnInfo(name = "cityId")
private var cityId:String ?=null
@ColumnInfo(name = "date")
private var date: String? = null
@ColumnInfo(name = "week")
private var week: String? = null
@ColumnInfo(name = "wea")
private var wea: String? = null
@ColumnInfo(name = "tem1")
private var tem1: String? = null
@ColumnInfo(name = "tem2")
private var tem2: String? = null
@ColumnInfo(name = "tem3")
private var tem3: String? = null

fun getDay(): String? {
return day;
}

fun setDay(day:String) {
this.day=day;
}
fun getCityId(): String? {
return cityId;
}
fun setCityId(cityid:String) {
this.cityId=cityid;
}

fun getDate():String? {
return date;
}
fun setDate(date:String) {
this.date=date;
}

fun getWeek():String?{
return week;
}

fun setWeek(week:String) {
this.week=week;
}
fun getWea():String? {
return wea;
}
fun setWea(wea:String) {
this.wea=wea;
}

fun getTem1():String?{
return tem1;
}

fun setTem1(tem1:String) {
this.tem1=tem1;
}
fun getTem2():String?{
return tem1;
}
fun setTem2(tem2:String) {
this.tem2=tem2;
}
fun getTem3():String?{
return tem1;
}

fun setTem3(tem3:String) {
this.tem3=tem3;
}

}

@qtybpg
Copy link
Author

qtybpg commented Jul 12, 2019

@dao
interface WeatherDao {

@Query("SELECT * FROM weather WHERE id = 101190401")
fun getWeatherById(): Single<CityAndWeather>

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertWeather(weather: CityAndWeather)

/**
 * Delete all users.
 */
@Query("DELETE FROM weather")
fun deleteAllWeather()

@Update(onConflict = OnConflictStrategy.REPLACE)
fun updateWeather(CityAndWeather: Weather)

}

@ditclear
Copy link
Owner

get set方法不需要的,把private 去掉.
另外,最好附上详细的错误信息

@qtybpg
Copy link
Author

qtybpg commented Jul 12, 2019

多谢大佬的指点,其实是我看的博客写的不全,在原作者的另一篇博客中已找到解决的方法,主要是我没加外键以及dao的原因

@qtybpg
Copy link
Author

qtybpg commented Jul 12, 2019

大佬,获取网上的数据,返回的却是空值,用的是嵌入的方式。
这是retrofit
val remote= Retrofit.Builder()
.baseUrl("https://www.tianqiapi.com/")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build().create(WeatherService::class.java)
这是service
interface WeatherService{
/**
* 文章详情
*/
@get("api/")
fun getWeather(@query("cityid") id: String): Single
@get("article_detail.php")
fun getArticleById(@query("id") id: Int): Single

}
这是实体类
class CityAndWeather{

@Embedded
public var weather:Weather?=null

@Relation(parentColumn = "id",entityColumn = "cityId",entity = WeatherData::class)
public var data:List<WeatherData>?=null;

}

@qtybpg
Copy link
Author

qtybpg commented Jul 12, 2019

@get("api/")
fun getWeather(@query("cityid") id: String): Single

@qtybpg
Copy link
Author

qtybpg commented Jul 12, 2019

打断点可以发现weather是null,而data里的item中cityid也为空
这是修改后的weather和weatherdata

@entity(tableName = "weather")
class Weather{
@PrimaryKey
@ColumnInfo(name = "id")
@nonnull
public var cityid: String?=null
@ColumnInfo(name = "updatetime")
public var update_time: String? = null
@ColumnInfo(name = "city")
public var city: String? = null
@ColumnInfo(name = "city_En")
public var cityEn: String? = null
@ColumnInfo(name = "country")
public var country: String? = null
@ColumnInfo(name = "country_En")
public var countryEn: String? = null
}

@entity(foreignKeys = arrayOf(ForeignKey(entity = Weather::class, parentColumns = arrayOf("id"), childColumns = arrayOf("cityId"),onDelete = CASCADE)),tableName = "weatherdata")
class WeatherData{
@PrimaryKey
@ColumnInfo(name = "day")
@nonnull
public var day: String?=null
@ColumnInfo(name = "cityId")
public var cityId:String ?=null
@ColumnInfo(name = "date")
public var date: String? = null
@ColumnInfo(name = "week")
public var week: String? = null
@ColumnInfo(name = "wea")
public var wea: String? = null
@ColumnInfo(name = "tem1")
public var tem1: String? = null
@ColumnInfo(name = "tem2")
public var tem2: String? = null
@ColumnInfo(name = "tem3")
public var tem3: String? = null
}

@qtybpg
Copy link
Author

qtybpg commented Jul 12, 2019

而如果将接口返回的数据修改为weather,却可以收到数据

@ditclear
Copy link
Owner

https://www.tianqiapi.com/api/?cityid=shanghai 接口是有返回数据的,看你模型是否对的上

@qtybpg
Copy link
Author

qtybpg commented Jul 12, 2019

emm,如果说api返回的模型使用的是weather而不是CityAndWeather的话是能获取到的,不过weather是使用注解@Embedded嵌入CityAndWeather中。所以获取不到数据。

@qtybpg
Copy link
Author

qtybpg commented Jul 15, 2019 via email

@qtybpg
Copy link
Author

qtybpg commented Jul 15, 2019

对了,还有这篇博客,是同一个作者https://blog.csdn.net/weixin_34304013/article/details/86842302

@ditclear
Copy link
Owner

返回的模型是这样的

按你现有的模型解析当然会不对,应该如下:

class CityAndWeather{

@PrimaryKey
@ColumnInfo(name = "id")
@nonnull
 var cityid: String?=null
@ColumnInfo(name = "updatetime")
var update_time: String? = null
@ColumnInfo(name = "city")
 var city: String? = null
@ColumnInfo(name = "city_En")
 var cityEn: String? = null

@Relation(parentColumn = "id",entityColumn = "cityId",entity = WeatherData::class)
public var data:List<WeatherData>?=null;
}

@qtybpg
Copy link
Author

qtybpg commented Jul 15, 2019 via email

@qtybpg
Copy link
Author

qtybpg commented Jul 31, 2019

大佬,看看我在你的paonet里的提问可以吗?我在看扔物线大佬写的rxjava入门中,看见了有个方法是unsubscribe,是为了解除引用,可是你在paonet中并未使用这个方法,你使用的数据类型是single,是不需要解除引用吗?

@ditclear
Copy link
Owner

unsubscribe 只是其中一种方式,现在用的较多的是AutoDispose和RxLifeCycle,达到的都是同样的效果

@qtybpg
Copy link
Author

qtybpg commented Jul 31, 2019

好的大佬,在捋了一遍你的代码后,看见你用的是AutoDispose解除引用了

@qtybpg
Copy link
Author

qtybpg commented Oct 11, 2019

大佬,有个问题想问下您啊,observeOn(AndroidSchedulers.mainThread())这句话如果放到single的doOn系列方法前面的话,对数据库的操作就会报错,用的是rxjava2,为什么啊?

@qtybpg
Copy link
Author

qtybpg commented Oct 11, 2019

remote.getWeather("d4UxIgoj","51735518")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSuccess {
local.deleteAllWeather(it.cityid)
local.insertWeather(it)
loading.set(false)
name.set(it.city)
}.doOnError{
Log.e("refresh",it.message)
error.set(it)
loading.set(false)
}
报的错误是 Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

@qtybpg
Copy link
Author

qtybpg commented Oct 11, 2019

remote.getWeather("d4UxIgoj","51735518")
.subscribeOn(Schedulers.io())
.doOnSuccess {
local.deleteAllWeather(it.cityid)
local.insertWeather(it)
loading.set(false)
name.set(it.city)
}.doOnError{
Log.e("refresh",it.message)
error.set(it)
loading.set(false)
}
.observeOn(AndroidSchedulers.mainThread())
将observeon放到doOn系列的后面就好事

@ditclear
Copy link
Owner

local.deleteAllWeather(it.cityid) 操作数据库的语句都需要放到子线程去,你把observeOn(AndroidSchedulers.mainThread())放到前面,相当于切到主线程去了,在主线程main里执行数据库操作自然会报错

@qtybpg
Copy link
Author

qtybpg commented Oct 11, 2019

所以observerOn也影响single本身是吗?我还以为只影响single的订阅者

@ditclear
Copy link
Owner

observerOn影响在它之后的,doonsuccess在它之后,所以切换到主线程去了

@qtybpg
Copy link
Author

qtybpg commented Oct 11, 2019

原来如此,多谢大佬

@qtybpg
Copy link
Author

qtybpg commented Oct 14, 2019

fun loadData(isRefresh: Boolean) = if (keyWord != null) {
repo.getSearchArticles(getPage(isRefresh), keyWord)
} else {
repo.getArticleList(getPage(isRefresh), tid)
}
.async(1000)
.map { articleList ->
with(articleList) {
loadMore.set(!incomplete_results)
if (isRefresh) {
list.clear()
}
return@map items?.map { ArticleItemViewModel(it) }?.let { list.addAll(it) }
}
}
大佬,看你的paonet实例代码,这段代码有点不清楚,你在这段代码中将articlist中的item转换成List并添加到adpter的list的操作我看懂了,可是rxjava.map将articllelist转换成boolean 的返回值
return@map items?.map { ArticleItemViewModel(it) }?.let { list.addAll(it) }这一段是怎么实现返回的是boolean的呢?

@ditclear
Copy link
Owner

写麻烦了,在.async(1000)用doOnSuccess{}就好,并不需要map

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants