我正在使用分页库从 api 检索数据并将它们显示在列表中
为此,我在我的存储库中创建了该方法:
fun getArticleList(query: String): Flow<PagingData<ArticleHeaderData>>
在我的视图模型中,我创建了如下所示的搜索方法:
override fun search(query: String) {
val lastResult = articleFlow
if (query == lastQuery && lastResult != null)
return
lastQuery = query
searchJob?.cancel()
searchJob = launch {
val newResult: Flow<PagingData<ArticleList>> = repo.getArticleList(query)
.map {
it.insertSeparators { //code to add separators }.cachedIn(this)
articleFlow = newResult
newResult.collectLatest {
articleList.postValue(it)
}
}
}
Run Code Online (Sandbox Code Playgroud)
为了测试我的视图模型,我使用测试方法PagingData.from来创建一个从我的模拟存储库返回的流,如下所示:
whenever(repo.getArticleList(query)).thenReturn(flowOf(PagingData.from(articles)))
然后我从 articleList LiveData 中检索实际的分页数据,如下所示:
val data = vm.articleList.value!!
这将返回一个PagingData<ArticleList>对象,我想验证它是否包含来自服务的数据(即articles,何时返回)
我发现这样做的唯一方法是创建以下扩展函数:
private val dcb = …Run Code Online (Sandbox Code Playgroud) 我升级了 android studio,我得到了这种奇怪的行为
当我运行我的单元测试时,它们会正确运行并完成(我引入了一些错误以确保确实如此)
但是当我在 java 中放置断点并使用调试测试时,jvm 会因以下错误而崩溃:
"C:\Program Files\Android\Android Studio4\jre\bin\java.exe" - agentlib:jdwp=transport=dt_socket,address=127.0.0.1:64493,suspend=y,server=n -ea -javaagent:C:\Users\imavrelos\.gradle\caches\modules-2\files-2.1\org.jetbrains.kotlinx\kotlinx-coroutines-core-jvm\1.3.9\4be434f5e86c1998a273e7f19a7286440894f0b0\kotlinx-coroutines-core-jvm-1.3.9.jar -Didea.test.cyclic.buffer.size=1048576 -javaagent:C:\Users\imavrelos\AppData\Local\Google\AndroidStudio4.1\groovyHotSwap\gragent.jar -javaagent:C:\Users\imavrelos\AppData\Local\Google\AndroidStudio4.1\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Android\Android Studio4\lib\idea_rt.jar" com.intellij.rt.execution.CommandLineWrapper C:\Users\imavrelos\AppData\Local\Temp\idea_classpath1657759720 com.intellij.rt.junit.JUnitStarter -ideVersion5 @w@C:\Users\imavrelos\AppData\Local\Temp\idea_working_dirs_junit.tmp @C:\Users\imavrelos\AppData\Local\Temp\idea_junit.tmp -socket64492
Connected to the target VM, address: '127.0.0.1:64493', transport: 'socket'
java.lang.NoClassDefFoundError: kotlin/collections/AbstractMutableMap
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:757)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
at java.lang.ClassLoader.loadClass(ClassLoader.java:419)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
at java.lang.ClassLoader.loadClass(ClassLoader.java:352)
at kotlinx.coroutines.debug.internal.DebugProbesImpl.<clinit>(DebugProbesImpl.kt:30)
at kotlinx.coroutines.debug.AgentPremain.<clinit>(AgentPremain.kt:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498) …Run Code Online (Sandbox Code Playgroud) 我们假设我有这两个对象
class Customer {
[PrimaryKey]
public string id;
[??????]
public List<int> addresses;
}
Run Code Online (Sandbox Code Playgroud)
和
class Address {
[PrimaryKey, AutoIncrement]
public int id;
public string street;
public int number;
}
Run Code Online (Sandbox Code Playgroud)
有没有办法使用SQLite.NET ORM来保存Customers对象?因为我很难保存列表.
如果没有这种方式,是否有某种我可以实现的事件或我可以覆盖的方法,以便当一个对象被加载时代码会触发?
我正在考虑在地址列表上方添加[忽略]的方法,当事件触发时我可以使用SQLite.net从另一个表加载地址的ID
提前感谢您提供的任何帮助
我使用MVP已有很长时间了,我开始转移到MVP和MVVM之间的混合状态
详细地,我的应用程序将如下所示:
我的问题:
例如,假设我有一个项目列表,而用户长按一个项目列表,则该体系结构的哪一部分应负责检查用户是否有权执行此操作,并让他们编辑该项目或显示错误信息?
例如,假设活动下面有3个片段,而一个ViewModel可以满足这些片段
我可以使用类似:
class MainViewModel : ViewModel() , IFragmentA, IFragmentB, IFragmentC
Run Code Online (Sandbox Code Playgroud)
然后,当我尝试在片段中获取ViewModel时,我可以编写如下内容:
lateinit var viewModel: IFragmentA
override fun onAttach(context: Context?) {
super.onAttach(context)
vm = ViewModelProviders.of(context as AppCompatActivity).get(IFragmentA::class.java)
}
Run Code Online (Sandbox Code Playgroud)
注意:我知道上面的代码不起作用,我要问的是是否有办法解决类似问题
例如,如果用户尝试删除条目,而我希望他们输入密码,则流程为:
感谢您提供任何帮助
android android-mvvm android-mvp android-architecture-components
我的视图模型包含一个非常简单的 recyclerview 适配器
当我尝试向它发送消息(依次调用notifyDatasetChanged)时,它会抛出这样的异常
java.lang.NullPointerException
at androidx.recyclerview.widget.RecyclerView$AdapterDataObservable.notifyChanged(RecyclerView.java:11996)
at
Run Code Online (Sandbox Code Playgroud)
问题是mObservers变量 fromAdapterDataObservable为空
问题是这扩展了Observable<AdapterDataObserver>它反过来定义mObservers为
protected final ArrayList<T> mObservers = new ArrayList<T>();
Run Code Online (Sandbox Code Playgroud)
所以基本上我的适配器被实例化的那一刻,它会调用
private final AdapterDataObservable mObservable = new AdapterDataObservable();
Run Code Online (Sandbox Code Playgroud)
(顺便调用,mObservable 不为空)
反过来应该调用 mObservers = new ArrayList<T>();
有人可以解释为什么从不调用它吗?或者是否有办法解决这个问题?
作为旁注,适配器不是模拟的,它是一个实体对象。
编辑:
这是我正在使用的测试代码:
class LoginViewModelTest {
private lateinit var vm: LoginViewModel
@get:Rule
val rule = InstantTaskExecutorRule()
@Before
fun setUp() {
whenever(settings.hasShownWelcome).thenReturn(false)
whenever(settings.serverIp).thenReturn("http://127.0.0.1")
//this is where the crash happens
vm = LoginViewModel(settings, service, app, TestLog, TestDispatchers) { …Run Code Online (Sandbox Code Playgroud) 我最近一直在研究Android,我试图将其中一个函数移植到C#compact framework.
我所做的是创建一个我称之为Activity的Abstract类.这个类看起来像这样
internal abstract class Activity
{
protected Form myForm;
private static Activity myCurrentActivity = null;
private static Activity myNextActivity = null;
internal static void LoadNext(Activity nextActivity)
{
myNextActivity = nextActivity;
if (myNextActivity != null)
{
myNextActivity.Show();
if (myCurrentActivity != null)
{
myCurrentActivity.Close();
myCurrentActivity = null;
}
myCurrentActivity = myNextActivity;
myNextActivity = null;
}
}
internal void Show()
{
//PROBLEM IS HERE
Application.Run(myForm);
//myForm.Show();
//myForm.ShowDialog();
//
}
internal void Close()
{
myForm.Close();
}
internal void GenerateForm()
{
///Code that …Run Code Online (Sandbox Code Playgroud) 我将很快开始研究xamarin,并将把很多代码从android studio的java转移到c#.
在java中我使用自定义类,它们被赋予参数条件等,将它们转换为SQL语句,然后将结果加载到项目模型中的对象
我不确定的是,linq是过滤此类数据的更好选择.
例如,目前会发生的事情就是沿着这些方向发展
List<Customer> customers = (new CustomerDAO()).get_all()
Run Code Online (Sandbox Code Playgroud)
或者,如果我有条件
List<Customer> customers = (new CustomerDAO()).get(new Condition(CustomerDAO.Code, equals, "code1")
Run Code Online (Sandbox Code Playgroud)
现在让我们假设我已经将类转移到了c#,我希望做一些类似于第二种情况的方法.
所以我可能会写下以下内容:
var customers = from customer
in (new CustomerDAO()).get_all()
where customer.code.equals("code1")
select customer
Run Code Online (Sandbox Code Playgroud)
我知道查询只会在我实际尝试访问客户时执行,但如果我有多次访问客户(让我们说我稍后使用4个foreach循环),get_all方法会被调用4次吗?或者是第一次执行时存储的结果?
它是否更有效(时间明智,因为内存方面可能不是)只保留get_all()方法并使用linq过滤结果?或者使用我现有的设置实际执行
Select * from Customers where code = 'code1'
Run Code Online (Sandbox Code Playgroud)
并将结果加载到对象?
提前感谢您提供的任何帮助
编辑:是的我知道有sqlite.net几乎可以做我的daos做但可能更好,并且在某些时候我可能会转换我的所有对象来使用它,我只需要知道为了知道
我有一个使用大量 textinputlayouts 的应用程序,因为我喜欢它们创建的样式
在一个屏幕上,我正在显示一个对象的信息,我希望它也看起来像用户使用 textinputedittexts 输入的数据,上面的小标题和下面的数据
现在我有一个 textinputlayout,下面有一个禁用的 textinputedittext
有没有办法让 textinputlayout 下的 textview 以相同的样式显示?
提前感谢您提供的任何帮助
编辑:
作为旁注,这是我目前用来完全禁用编辑文本的内容
<android.support.design.widget.TextInputLayout
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/name"
tools:text="This is where the name goes"
android:inputType="none"
android:clickable="false"
android:cursorVisible="false"
android:focusable="false"
android:focusableInTouchMode="false" />
Run Code Online (Sandbox Code Playgroud)
我试图避免的不是在我尝试创建的每个视图中使用 clickable 和 inputtype 等,而是使用单个视图
所以除了创建一个以各种方式启动 unclickabke 的自定义编辑文本(如 NeverEnabledEditText),或者将所有这些属性添加到我的 xml 中,有没有办法做到以上几点?
我有一个片段,我用一个新的事务替换
该Fragment包含一个包含大量项目的RecyclerView.
当用户按下新片段上的完成按钮时,我弹出后台堆栈,并重新创建旧片段.
这会导致再次调用OnCreateView方法,一切正常.
我的问题是它中的RecyclerView被重新创建,适配器被重置,但它似乎自动移动到它离开的位置(我假设只有在我使用事务添加而不是事务替换时才会发生)
作为旁注,适配器仍然为可见项调用OnBindViewHolder和OnCreateViewHolder.
我的问题是,为什么会发生这种情况?因为重新创建整个片段不应该重置到第一个位置?除了在加载新片段之前手动调用scrollToPosition(0)之外,还有另一种方法可以使片段不记得任何内容并在返回时实际完全重新创建吗?
我有一个场景,我的代码必须发送 api 调用并继续其工作(其中包含另一个 api 调用),而不等待第一次调用的结果。
现在我在我的视图模型中执行此操作
fun showItem(id:Int) {
launch{
repo.markItemRead(id)
}
launch {
try {
val item = repo.getItemById(id).getOrThrow
commands.postValue(ShowItemCommand(item))
} catch (t:Throwable) {
commands.postValue(ShowError(R.string.error_retrieve_item))
repo.logError(t)
}
}
}
Run Code Online (Sandbox Code Playgroud)
这调用了具有这两个功能的存储库
suspend fun markItemRead(id) {
try {
service.markItemAsRead(id)
} catch(ignored:Throwable) {
}
}
suspend fun getItemById(id) : Result<ItemData> {
return try {
val response : ItemEntity = service.getItemById(id)
val item = response.toData()
Result.Success(item)
} catch (t:Throwable) {
Result.Failure(t)
}
}
Run Code Online (Sandbox Code Playgroud)
如果存储库完成所有这些工作,我会更喜欢它,因为每次都必须遵循另一项工作。
不幸的是,当我尝试在我的存储库中执行类似的操作时:
suspend fun getItemById(id:Int) : Result<ItemData> {
try { …Run Code Online (Sandbox Code Playgroud) android ×7
c# ×3
unit-testing ×3
android-architecture-components ×1
android-mvp ×1
android-mvvm ×1
coroutine ×1
kotlin ×1
linq ×1
sqlite.net ×1
winforms ×1
xamarin ×1