小编Cru*_*ces的帖子

在 Android 单元测试中检查来自 PagingData 对象的数据的正确方法是什么

我正在使用分页库从 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 unit-testing android-paging

17
推荐指数
1
解决办法
1810
查看次数

单元测试在运行时正常工作,但在 Android Studio 4.1 中调试时不工作

我升级了 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)

android unit-testing

15
推荐指数
3
解决办法
2416
查看次数

如何在SQLite.net中存储对象列表?

我们假设我有这两个对象

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

提前感谢您提供的任何帮助

c# xamarin sqlite.net

8
推荐指数
1
解决办法
9993
查看次数

有关Android体系结构组件中每个组件的责任的问题

我使用MVP已有很长时间了,我开始转移到MVP和MVVM之间的混合状态

详细地,我的应用程序将如下所示:

  • 每个活动都有一个0到x个代表其视图的片段
  • 每个片段都将请求活动的ViewModel,以便他们可以使用LiveData检索数据
  • 该活动将有一个单独的ViewModel,它将充当演示者。创建后,将向ViewModel注入带有LiveData的Activity的ViewModel,以便可以根据需要更新UI
  • 演示者将获取发送到数据ViewModel的消息,并将结果发送回给它。

我的问题:

  1. 可以在演示者ViewModel中保留对数据ViewModel的引用会导致内存泄漏或诸如内存泄漏之类的不利影响吗?
  2. 业务逻辑应该在哪里?在演示者中还是在模型部分中?

例如,假设我有一个项目列表,而用户长按一个项目列表,则该体系结构的哪一部分应负责检查用户是否有权执行此操作,并让他们编辑该项目或显示错误信息?

  1. 片段是否有办法仅获得Activity的ViewModel的一部分?

例如,假设活动下面有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)

注意:我知道上面的代码不起作用,我要问的是是否有办法解决类似问题

  1. 将消息发送回活动SingleEvents的正确方法是吗?

例如,如果用户尝试删除条目,而我希望他们输入密码,则流程为:

  • Fragment发送消息以将其删除到其ViewModel
  • ViewModel将其传递给Presenter
  • 演示者决定继续进行操作之前需要密码验证
  • 演示者在ViewModel中设置SingleEvent的值
  • ViewModel通知事件的订阅者(在本例中为MainActivity)他们应该显示一个对话框,要求输入密码

感谢您提供任何帮助

android android-mvvm android-mvp android-architecture-components

8
推荐指数
1
解决办法
273
查看次数

访问 mObservables 时,单元测试 RecyclerView 适配器抛出 NullPointerException

我的视图模型包含一个非常简单的 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 unit-testing android-recyclerview

8
推荐指数
1
解决办法
679
查看次数

在C#cf中显示在下一个表单之后关闭表单

我最近一直在研究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)

c# compact-framework winforms

6
推荐指数
1
解决办法
707
查看次数

linq如何实际执行代码以从数据源检索数据?

我将很快开始研究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做但可能更好,并且在某些时候我可能会转换我的所有对象来使用它,我只需要知道为了知道

c# linq

6
推荐指数
1
解决办法
157
查看次数

你能在 textinputlayout 中添加一个 textview 或类似的东西吗?

我有一个使用大量 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 中,有没有办法做到以上几点?

android android-textinputlayout

6
推荐指数
1
解决办法
2526
查看次数

在弹出后备箱后,RecyclerView在重新创建时是否应该记住它的位置?

我有一个片段,我用一个新的事务替换

该Fragment包含一个包含大量项目的RecyclerView.

当用户按下新片段上的完成按钮时,我弹出后台堆栈,并重新创建旧片段.

这会导致再次调用OnCreateView方法,一切正常.

我的问题是它中的RecyclerView被重新创建,适配器被重置,但它似乎自动移动到它离开的位置(我假设只有在我使用事务添加而不是事务替换时才会发生)

作为旁注,适配器仍然为可见项调用OnBindViewHolder和OnCreateViewHolder.

我的问题是,为什么会发生这种情况?因为重新创建整个片段不应该重置到第一个位置?除了在加载新片段之前手动调用scrollToPosition(0)之外,还有另一种方法可以使片段不记得任何内容并在返回时实际完全重新创建吗?

android android-fragments android-recyclerview

6
推荐指数
1
解决办法
599
查看次数

如何在另一个函数中运行一个挂起函数而不等待其结果?

我有一个场景,我的代码必须发送 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 coroutine kotlin kotlin-coroutines coroutinescope

6
推荐指数
1
解决办法
5102
查看次数