草庐IT

java - 列表的值不会以编程方式更改

coder 2023-12-22 原文

我的 Activity 中有一个名为 messages 属性的 List。在 synchronization() 中,我调用了 getDateMessage(upadated_at) 函数。在此函数中,messages 的值已更改,但当程序转到同步 时,messages 列表为空。

private List<message_model> messages = new ArrayList<>();
private void synchronization() {
getDateMessage(upadated_at);
    Log.e("MSDF",messages.toString()+" list tostring");
}
  private void getDateMessage(String date) {
    MessengerActivity.APIInterface apiInterface = app_net.getRetrofitInstance().create(MessengerActivity.APIInterface.class);
    retrofit2.Call<List<message_model>> call = apiInterface.getMessageDate(Ptoken, date);
    call.enqueue(new Callback<List<message_model>>() {
        @Override
        public void onResponse(Call<List<message_model>> call, Response<List<message_model>> response) {
            if(response.isSuccessful()) {
                messages.addAll(response.body());
                Log.e("MSDF",response.body().toString()+" responsebody in call");
                Log.e("MSDF",messages.toString()+" message in call");
                Log.e("MESSAGE", "getDateMessage successful");
            }
        }
        @Override
        public void onFailure(Call<List<message_model>> call, Throwable t) {
            Log.e("MESSAGE", "getDateMessage" + t.toString());
        }
    });
}

这是我的 logcat。

    09-30 14:34:53.714 10763-10763/idea.mahdi.bime E/MSDF: [] list tostring
09-30 14:34:54.104 10763-10763/idea.mahdi.bime E/MSDF: [message_model{id=33, thread_id=2, user_id=15, body='چطوری', created_at='2018-09-29 10:28:26', updated_at='2018-09-29 10:28:26', deleted_at='null'}, message_model{id=30, thread_id=2, user_id=15, body='سلام', created_at='2018-09-29 09:30:40', updated_at='2018-09-29 09:30:40', deleted_at='null'}, message_model{id=7, thread_id=2, user_id=15, body='hi', created_at='2018-09-24 09:55:46', updated_at='2018-09-24 09:55:46', deleted_at='null'}] responsebody in api
09-30 14:34:54.104 10763-10763/idea.mahdi.bime E/MSDF: [message_model{id=33, thread_id=2, user_id=15, body='چطوری', created_at='2018-09-29 10:28:26', updated_at='2018-09-29 10:28:26', deleted_at='null'}, message_model{id=30, thread_id=2, user_id=15, body='سلام', created_at='2018-09-29 09:30:40', updated_at='2018-09-29 09:30:40', deleted_at='null'}, message_model{id=7, thread_id=2, user_id=15, body='hi', created_at='2018-09-24 09:55:46', updated_at='2018-09-24 09:55:46', deleted_at='null'}] message in api
09-30 14:34:54.104 10763-10763/idea.mahdi.bime 
E/MESSAGE: getDateMessage successful

最佳答案

问题在于,当您调用 getDataMessage() 时,它会执行异步调用(改型 enqueue() 方法)。将调用服务器以在后台线程中获取消息,而 android 应用程序将保留在主线程中。

因此,Log.e("MSDF",messages.toString()+"list tostring"); 在改造调用之前被调用,因此,目前还没有可用的数据.您应该确保在数据加载完成后对数据执行某些操作。

private List<message_model> messages = new ArrayList<>();
private void synchronization() {
getDateMessage(upadated_at);
    // Anything you put here will be called before the data (messages) is loaded.
    // Do not work with your messages here, they'll be null.
}
  private void getDateMessage(String date) {
    MessengerActivity.APIInterface apiInterface = app_net.getRetrofitInstance().create(MessengerActivity.APIInterface.class);
    retrofit2.Call<List<message_model>> call = apiInterface.getMessageDate(Ptoken, date);
    call.enqueue(new Callback<List<message_model>>() {
        @Override
        public void onResponse(Call<List<message_model>> call, Response<List<message_model>> response) {
            if(response.isSuccessful()) {
                messages.addAll(response.body());
                Log.e("MSDF",response.body().toString()+" responsebody in call");
                Log.e("MSDF",messages.toString()+" message in call");
                Log.e("MESSAGE", "getDateMessage successful");
                // Anything you want to do with the messages should be placed here. When you are sure the data is completed. 
                Log.e("MSDF",messages.toString()+" list tostring");
            }
        }
        @Override
        public void onFailure(Call<List<message_model>> call, Throwable t) {
            Log.e("MESSAGE", "getDateMessage" + t.toString());
        }
    });
}

在使用它避免 NPE 之前检查 if (response.body() != null) 是值得的。

编辑

正如评论中所问的那样。一个好的解决方案(Google 推荐)是使用 View 模型获取数据,如 this android dev guide article 中所述。 .

ViewModel 方法很好,因为:

  • 数据在配置更改期间保持不变(例如,如果您旋转设备,您的消息列表将仍在您的应用中)。
  • 它不会导致内存泄漏。
  • 您将 View 数据所有权与 UI Controller 逻辑分开。

其他的优势可以看文章。

1 - 在您的 build.gradle(Module:app) 文件中添加 View 模型依赖项

dependencies {
    def lifecycle_version = "1.1.1"

    // ViewModel and LiveData
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"
}

参见 here最新版本。

2 - 创建一个 ViewModel 类

MessageViewModel.java

public class MessagesViewModel extends ViewModel {
    private MutableLiveData<List<message_model>> messagesList;
    public LiveData<List<message_model>> getMessages() {
        if (messagesList == null) {
            messagesList = new MutableLiveData<List<message_model>>();
            loadMessages();
        }
        return messagesList;
    }

    private void loadMessages() {
        MessengerActivity.APIInterface apiInterface = app_net.getRetrofitInstance().create(MessengerActivity.APIInterface.class);
        retrofit2.Call<List<message_model>> call = apiInterface.getMessageDate(Ptoken, date);
        call.enqueue(new Callback<List<message_model>>() {
        @Override
        public void onResponse(Call<List<message_model>> call, Response<List<message_model>> response) {
            if(response.isSuccessful()) {
                if (response.body() != null) {
                    messagesList.setValue(response.body());
                }
            }
        }
        @Override
        public void onFailure(Call<List<message_model>> call, Throwable t) {
            // Handle failure
        }
        });
    }
}

3 - 获取 Activity 中的消息

public class MainActivity extends AppCompatActivity {
    public void onCreate(Bundle savedInstanceState) {
        // Create a ViewModel the first time the system calls an activity's onCreate() method.
        // Re-created activities receive the same MyViewModel instance created by the first activity.

        MessagesViewModel model = ViewModelProviders.of(this).get(MessagesViewModel.class);
        model.getMessages().observe(this, messagesList -> {
            // Do whatever you want with the list of messages.
        });
    }
}

看看您的 Activity 现在有多干净。

然后你可以实现一个SwipeRefreshLayout如果您想让您的用户刷新数据。

如果不够可以查看这个ReposViewModel

最后,如果调用改造是您要向公众发布的应用程序的主要核心,您应该使用 Dagger 2 和 RxJava 引入 MVVM 方法,如 this article 中所述。 . (这是进阶)

关于java - 列表的值不会以编程方式更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52577417/

有关java - 列表的值不会以编程方式更改的更多相关文章

  1. ruby-on-rails - Ruby on Rails 迁移,将表更改为 MyISAM - 2

    如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设

  2. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  4. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

  5. ruby - RVM 使用列表[0] - 2

    是否有类似“RVMuse1”或“RVMuselist[0]”之类的内容而不是键入整个版本号。在任何时候,我们都会看到一个可能包含5个或更多ruby的列表,我们可以轻松地键入一个数字而不是X.X.X。这也有助于rvmgemset。 最佳答案 这在RVM2.0中是可能的=>https://docs.google.com/document/d/1xW9GeEpLOWPcddDg_hOPvK4oeLxJmU3Q5FiCNT7nTAc/edit?usp=sharing-知道链接的任何人都可以发表评论

  6. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  7. ruby - Capistrano 3 在任务中更改 ssh_options - 2

    我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe

  8. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  9. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

  10. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

随机推荐