- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在构建一个应用程序,该应用程序使用 ArticleBoundaryCallback 来初始化对 API 的调用,并将响应存储在 Room 中。我也在使用 LiveData 收听该表,并在 PagedListAdapter 中显示项目。
问题是每次在 Room 的(文章)表中插入新数据时,整个列表都会刷新。
此外,在配置更改时,似乎再次获取了整个数据(ViewModel 不保留它,RecyclerView 被重新创建)。
在每次插入时, RecyclerView 都会跳转(如果插入的是新数据,则跳转几行,或者如果它用旧数据替换新数据,则在开头)。
整个代码在这个 GitHub repo .
我的类(class)是:
文章:
@Entity(tableName = "article",
indices={@Index(value="id")})public class Article {
@PrimaryKey(autoGenerate = false)
@SerializedName("_id")
@Expose
@NonNull
private String id;
@SerializedName("web_url")
@Expose
private String webUrl;
@SerializedName("snippet")
@Expose
private String snippet;
@SerializedName("print_page")
@Expose
private String printPage;
@SerializedName("source")
@Expose
private String source;
@SerializedName("multimedia")
@Expose
@Ignore
private List<Multimedium> multimedia = null;
@Dao
public interface ArticleDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
long insert(Article article);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void update(Article... repos);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertArticles(List<Article> articles);
@Delete
void delete(Article... articles);
@Query("DELETE FROM article")
void deleteAll();
@Query("SELECT * FROM article")
List<Article> getArticles();
@Query("SELECT * FROM article")
DataSource.Factory<Integer, Article> getAllArticles();}
public class LocalCache {
private static final String TAG = LocalCache.class.getSimpleName();
private ArticleDao articleDao;
private Executor ioExecutor;
public LocalCache(AppDatabase appDatabase, Executor ioExecutor) {
this.articleDao = appDatabase.getArticleDao();
this.ioExecutor = ioExecutor;
}
public void insertAllArticles(List<Article> articleArrayList){
ioExecutor.execute(new Runnable() {
@Override
public void run() {
Log.d(TAG, "inserting " + articleArrayList.size() + " repos");
articleDao.insertArticles(articleArrayList);
}
});
}
public void otherFunction(ArrayList<Article> articleArrayList){
// TODO
}
public DataSource.Factory<Integer, Article> getAllArticles() {
return articleDao.getAllArticles();
}
public class AppRepository {
private static final String TAG = AppRepository.class.getSimpleName();
private static final int DATABASE_PAGE_SIZE = 20;
private Service service;
private LocalCache localCache;
private LiveData<PagedList<Article>> mPagedListLiveData;
public AppRepository(Service service, LocalCache localCache) {
this.service = service;
this.localCache = localCache;
}
/**
* Search - match the query.
*/
public ApiSearchResultObject search(String q){
Log.d(TAG, "New query: " + q);
// Get data source factory from the local cache
DataSource.Factory dataSourceFactory = localCache.getAllArticles();
// every new query creates a new BoundaryCallback
// The BoundaryCallback will observe when the user reaches to the edges of
// the list and update the database with extra data
ArticleBoundaryCallback boundaryCallback = new ArticleBoundaryCallback(q, service, localCache);
// Get the paged list
LiveData data = new LivePagedListBuilder(dataSourceFactory, DATABASE_PAGE_SIZE)
.setBoundaryCallback(boundaryCallback)
.build();
mPagedListLiveData = data;
ApiSearchResultObject apiSearchResultObject = new ApiSearchResultObject();
apiSearchResultObject.setArticles(data);
return apiSearchResultObject;
}
public DataSource.Factory getAllArticles() {
return localCache.getAllArticles();
}
public void insertAllArticles(ArrayList<Article> articleList) {
localCache.insertAllArticles(articleList);
}
}
public class DBArticleListViewModel extends ViewModel {
private AppRepository repository;
// init a mutable live data to listen for queries
private MutableLiveData<String> queryLiveData = new MutableLiveData();
// make the search after each new search item is posted with (searchRepo) using "map"
private LiveData<ApiSearchResultObject> repositoryResult = Transformations.map(queryLiveData, queryString -> {
return repository.search(queryString);
});
// constructor, init repo
public DBArticleListViewModel(@NonNull AppRepository repository) {
this.repository = repository;
}
// get my Articles!!
public LiveData<PagedList<Article>> articlesLiveData = Transformations.switchMap(repositoryResult, object ->
object.getArticles());
// get teh Network errors!
public LiveData<String> errorsLiveData = Transformations.switchMap(repositoryResult, object ->
object.getNetworkErrors());
// Search REPO
public final void searchRepo(@NonNull String queryString) {
this.queryLiveData.postValue(queryString);
}
// LAST Query string used
public final String lastQueryValue() {
return (String)this.queryLiveData.getValue();
}
DummyPagedListAdapter articleListAdapter = new DummyPagedListAdapter(this);
localDBViewModel = ViewModelProviders.of(this, Injection.provideViewModelFactory(this)).get(DBArticleListViewModel.class);
localDBViewModel.articlesLiveData.observe(this, pagedListLiveData ->{
Log.d(TAG, "articlesLiveData.observe size: " + pagedListLiveData.size());
if(pagedListLiveData != null)
articleListAdapter.submitList(pagedListLiveData);
});
recyclerView.setAdapter(articleListAdapter);
public class DummyPagedListAdapter extends PagedListAdapter<Article, ArticleViewHolder> {
private final ArticleListActivity mParentActivity;
public DummyPagedListAdapter(ArticleListActivity parentActivity) {
super(Article.DIFF_CALLBACK);
mParentActivity = parentActivity;
}
@NonNull
@Override
public ArticleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(mParentActivity).inflate(R.layout.article_list_content, parent, false);
return new ArticleViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull ArticleViewHolder holder, int position) {
Article article = getItem(position);
if (article != null) {
holder.bindTo(article);
} else {
holder.clear();
}
}
}
public static DiffUtil.ItemCallback<Article> DIFF_CALLBACK = new
DiffUtil.ItemCallback<Article>() {
@Override
public boolean areItemsTheSame(@NonNull Article oldItem, @NonNull
Article newItem) {
return oldItem.getId() == newItem.getId();
}
@Override
public boolean areContentsTheSame(@NonNull Article oldItem, @NonNull
Article newItem) {
return oldItem.getWebUrl() == newItem.getWebUrl();
}
};
最佳答案
是的..花了我一段时间但我解决了它。正如我所想的,愚蠢的问题:在适配器用来决定从观察到的数据集中添加什么和忽略什么的 DIFF_CALLBACK 中,我使用作为比较器 oldItem.getId() == newItem.getId() 这是字符串! !!当然,适配器总是获得“新值”并添加它们。
更正 DiffUtil.ItemCallback
public static DiffUtil.ItemCallback<Article> DIFF_CALLBACK = new DiffUtil.ItemCallback<Article>() {
@Override
public boolean areItemsTheSame(@NonNull Article oldItem, @NonNull Article newItem) {
return oldItem.getStoreOrder() == newItem.getStoreOrder();
}
@Override
public boolean areContentsTheSame(@NonNull Article oldItem, @NonNull Article newItem) {
return oldItem.getId().equals(newItem.getId()) && oldItem.getWebUrl().equals(newItem.getWebUrl());
}
};
关于android-viewmodel - 从 Room 观察 LiveData 会导致 PagedListAdapter 刷新,ViewModel 也会在方向更改时刷新数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51455071/
SQLite、Content provider 和 Shared Preference 之间的所有已知区别。 但我想知道什么时候需要根据情况使用 SQLite 或 Content Provider 或
警告:我正在使用一个我无法完全控制的后端,所以我正在努力解决 Backbone 中的一些注意事项,这些注意事项可能在其他地方更好地解决......不幸的是,我别无选择,只能在这里处理它们! 所以,我的
我一整天都在挣扎。我的预输入搜索表达式与远程 json 数据完美配合。但是当我尝试使用相同的 json 数据作为预取数据时,建议为空。点击第一个标志后,我收到预定义消息“无法找到任何内容...”,结果
我正在制作一个模拟 NHL 选秀彩票的程序,其中屏幕右侧应该有一个 JTextField,并且在左侧绘制弹跳的选秀球。我创建了一个名为 Ball 的类,它实现了 Runnable,并在我的主 Draf
这个问题已经有答案了: How can I calculate a time span in Java and format the output? (18 个回答) 已关闭 9 年前。 这是我的代码
我有一个 ASP.NET Web API 应用程序在我的本地 IIS 实例上运行。 Web 应用程序配置有 CORS。我调用的 Web API 方法类似于: [POST("/API/{foo}/{ba
我将用户输入的时间和日期作为: DatePicker dp = (DatePicker) findViewById(R.id.datePicker); TimePicker tp = (TimePic
放宽“邻居”的标准是否足够,或者是否有其他标准行动可以采取? 最佳答案 如果所有相邻解决方案都是 Tabu,则听起来您的 Tabu 列表的大小太长或您的释放策略太严格。一个好的 Tabu 列表长度是
我正在阅读来自 cppreference 的代码示例: #include #include #include #include template void print_queue(T& q)
我快疯了,我试图理解工具提示的行为,但没有成功。 1. 第一个问题是当我尝试通过插件(按钮 1)在点击事件中使用它时 -> 如果您转到 Fiddle,您会在“内容”内看到该函数' 每次点击都会调用该属
我在功能组件中有以下代码: const [ folder, setFolder ] = useState([]); const folderData = useContext(FolderContex
我在使用预签名网址和 AFNetworking 3.0 从 S3 获取图像时遇到问题。我可以使用 NSMutableURLRequest 和 NSURLSession 获取图像,但是当我使用 AFHT
我正在使用 Oracle ojdbc 12 和 Java 8 处理 Oracle UCP 管理器的问题。当 UCP 池启动失败时,我希望关闭它创建的连接。 当池初始化期间遇到 ORA-02391:超过
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve
引用这个plunker: https://plnkr.co/edit/GWsbdDWVvBYNMqyxzlLY?p=preview 我在 styles.css 文件和 src/app.ts 文件中指定
为什么我的条形这么细?我尝试将宽度设置为 1,它们变得非常厚。我不知道还能尝试什么。默认厚度为 0.8,这是应该的样子吗? import matplotlib.pyplot as plt import
当我编写时,查询按预期执行: SELECT id, day2.count - day1.count AS diff FROM day1 NATURAL JOIN day2; 但我真正想要的是右连接。当
我有以下时间数据: 0 08/01/16 13:07:46,335437 1 18/02/16 08:40:40,565575 2 14/01/16 22:2
一些背景知识 -我的 NodeJS 服务器在端口 3001 上运行,我的 React 应用程序在端口 3000 上运行。我在 React 应用程序 package.json 中设置了一个代理来代理对端
我面临着一个愚蠢的问题。我试图在我的 Angular 应用程序中延迟加载我的图像,我已经尝试过这个2: 但是他们都设置了 src attr 而不是 data-src,我在这里遗漏了什么吗?保留 d
我是一名优秀的程序员,十分优秀!