在 Parse Query 中初始化或修改变量

Posted

技术标签:

【中文标题】在 Parse Query 中初始化或修改变量【英文标题】:Initializing or modifying variable in Parse Query 【发布时间】:2018-08-12 17:06:03 【问题描述】:

我创建了一个名为“Roommate”的类,它是使用 ParseUser 变量构造的,我尝试创建一个新的 Roommate 对象并将其添加到我的 Roommate arrayList。但是,查询完成后,似乎我所做的任何修改或初始化都会被重置。查询完成后,我的 arrayList 最终为空。有谁知道这是为什么以及我可以做些什么来解决这个问题?

如果这是一个基本问题,我深表歉意。我是一名学生,这是我第一次尝试制作应用程序。感谢所有反馈。

我调用 updateRoommatesArray() 的 ArrayList 和 OnCreate 方法:

// variables
private ArrayList<Roommate> roommates = new ArrayList<>();
AddRoommateRecyclerViewAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_add_roommates);

    // Set up toolbar
    Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar_roommate);
    setSupportActionBar(myToolbar);

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setTitle("Add Roommates");

    // Set up floating action button
    FloatingActionButton fab = findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View view) 
            //show dialog on click
            AddRoommatesDialog addRoommatesDialog = new AddRoommatesDialog();
            addRoommatesDialog.show(getSupportFragmentManager(),"add roommates dialog");
        
    );

    // Initializes roommateNames with data from Parse
    updateRoommatesArray();
    Toast.makeText(this, Integer.toString(roommates.size()), Toast.LENGTH_SHORT).show();

    // Set up Recycler View
    LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
    RecyclerView recyclerView = findViewById(R.id.rm_recycler);
    recyclerView.setLayoutManager(layoutManager);
    adapter = new AddRoommateRecyclerViewAdapter(this, roommates);
    recyclerView.setAdapter(adapter);


updateRoommatesArray 方法:

public void updateRoommatesArray() 
    roommates.clear();
    final ParseUser currentUser = ParseUser.getCurrentUser();
    ParseRelation<ParseUser> relation = currentUser.getRelation("roommates");
    relation.getQuery().findInBackground(new FindCallback<ParseUser>() 
        @Override
        public void done(List<ParseUser> objects, ParseException e) 
            if (e == null && objects.size() > 0) 
                for (ParseUser roommate : objects) 
                    Roommate current_roommate = new Roommate(roommate);
                    roommates.add(current_roommate);
                
            
            else 
                Log.i("Query", "Empty or Not Working");
            
        
    );

室友班:

public class Roommate 

// Member Variables
String objectId;
String username;
String firstName;
String lastName;
String fullName;
ArrayList<Roommate> roommates;


// Constructor
public Roommate(ParseUser user_in) 
    objectId = user_in.getObjectId().toString();
    username = user_in.getUsername().toString();
    firstName = user_in.get("firstName").toString();
    lastName = user_in.get("lastName").toString();
    fullName = firstName + " " + lastName;
    roommates = new ArrayList<>();



public String getObjectId() 
    return objectId;


public String getUsername() 
    return username;


public String getFirstName() 
    return firstName;


public String getLastName() 
    return lastName;


public String getFullName() 
    return fullName;


public ArrayList<Roommate> getRoommates() 
    return roommates;


【问题讨论】:

【参考方案1】:

问题刚刚出现,因为findInBackground()方法是异步方法调用。无法保证设置 RecyclerAdaptor 的适配器会在终止 findInBackground 的作业后执行。

请注意,您在 updateRoommatesArray 的第一行中清楚地列出了列表。然后你开始一个异步任务。之后主线程想要继续它的工作并返回到 onCreate() 方法来设置 ArrayList。它将无限期地发生。

从本质上讲,从数据库加载数据将比在主线程中执行简单的代码花费更长的时间。

所以很可能 recyclerView.setAdapter(adapter);将在数组被填充到 done() 方法之前执行。

为了确保适配器将被填充,请将以下代码放入 done 方法中。这样做,您将保证正确的代码执行顺序。

Toast.makeText(this, Integer.toString(roommates.size()), Toast.LENGTH_SHORT).show();

    // Set up Recycler View
    LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
    RecyclerView recyclerView = findViewById(R.id.rm_recycler);
    recyclerView.setLayoutManager(layoutManager);
    adapter = new AddRoommateRecyclerViewAdapter(this, roommates);
    recyclerView.setAdapter(adapter);

【讨论】:

谢谢你说得通。如果我不能确定 findInBackground() 方法何时完成,有什么方法可以在另一个函数中访问存储在室友 arrayList 中的值? 如果您熟悉 EDA,您可以引发一个事件并在主线程下运行的所需订阅者中捕获它,请参阅 GreenRobot EventBus。在任何情况下,您都必须确保填充 RecyclerAdapter 的调用方法必须在 done() 方法完成它的工作之后发生。这是完全并发的问题,你必须小心它

以上是关于在 Parse Query 中初始化或修改变量的主要内容,如果未能解决你的问题,请参考以下文章

在 Parse 服务器 CloudCode 中使用已初始化的邮件适配器

java成员变量和局部变量的初始化和内存中的运行机制

const,var,let笔记

java中成员或类变量自动初始化是啥意思

Unity 脚本中公共变量初始化值修改后,为啥Inpector面板的对应变量属性不更新?

云代码 - Parse.Object 初始化程序不起作用