有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

安卓让Java线程等待值

我需要从Firebase数据库的UID中检索用户名。这是我做这件事的代码,但我不知道如何让它工作。该线程来自:

final String[] returnName = new String[1];

立即发送至:

return returnName[0].toString();

不必等待它首先从侦听器填充数据,因此返回值为null,应用程序崩溃。以下是本模块的完整代码:

private synchronized String getFriendName(String key) {
    final String[] returnName = new String[1];
    DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Profiles").child(key).child("Name");
    ref.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for (DataSnapshot datas : dataSnapshot.getChildren()) {
                String userResult = datas.getKey();
                if (userResult != null) {
                    returnName[0] = dataSnapshot.getValue().toString();
                    String temp = dataSnapshot.getValue().toString();
                    Toast.makeText(getBaseContext(), "Step 1: " + temp, Toast.LENGTH_SHORT).show();
                    Toast.makeText(getBaseContext(), "Step 2: " + returnName[0], Toast.LENGTH_SHORT).show();
                }
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
    return returnName[0].toString();
}

我花了数小时阅读和尝试一些东西来让它工作,但我无法在触发返回值之前让代码真正正确地执行

有人能帮我吗

@TaherKorshidi 这是调用此函数的代码:

GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(currentLocation.latitude, currentLocation.longitude), radius);
geoQuery.removeAllListeners();

geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
    @Override
    public void onKeyEntered(String key, GeoLocation location) {
        friendID = key;
        String friend = getFriendName(friendID);
    }
}

答案,@TaherKorshidi答案是在同一个侦听器中获取其他值。没有别的办法,我也不知道该怎么做,直到你把我引向这个方向。工作解决方案:

geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
                @Override
                public void onKeyEntered(String key, GeoLocation location) {
                    getFriendKey = key;
                    if (getFriendKey != ping_userID) {
                        for(ContactsList d : UserList){
                            if(d.getUID() != null && d.getUID().contains(getFriendKey)) {
                                friendName = d.getName();
                            }
                        }
                        Toast.makeText(getBaseContext(), "Name: " + String.valueOf(friendName), Toast.LENGTH_SHORT).show();
                        getFriendLocation(getFriendKey, friendName);
                    }
                }

共 (2) 个答案

  1. # 1 楼答案

    您可以使用asyncTask实现此目的,如下所示

    public static class GetFriendName extends AsyncTask<String, Void, Void>{
    
        String returnName;
    
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            //Show progress bar
        }
    
        @Override
        protected Void doInBackground(String... strings) {
            DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Profiles").child(key).child("Name");
            ref.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    for (DataSnapshot datas : dataSnapshot.getChildren()) {
                        String userResult = datas.getKey();
                        if (userResult != null) {
                            returnName = dataSnapshot.getValue().toString();
                            String temp = dataSnapshot.getValue().toString();
                        }
                    }
                }
    
                @Override
                public void onCancelled(DatabaseError databaseError) {
    
                }
            });
            return null;
        }
    
        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            //Dismiss progress bar
            showFriendName(returnName);
        }
    }
    

    您可以从onCreate()调用这个类,如下所示

    GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(currentLocation.latitude, currentLocation.longitude), radius);
    geoQuery.removeAllListeners();
    
    geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
        @Override
        public void onKeyEntered(String key, GeoLocation location) {
            friendID = key;
            new GetFriendName().execute(friendID);
        }
    }
    

    然后你可以使用这个方法将你的friendName分配给一个字符串值,并在那里完成你的工作

    private static void showFriendName(String friendName){
        Toast.makeText(stackOverflowActivity, ""+friendName, Toast.LENGTH_SHORT).show();
        String friend = friendName;
        //Do your work here
    }
    

    此方法正在从onPostExecute()调用

  2. # 2 楼答案

    一种方法是使用CountDownLatch类:

    private synchronized String getFriendName(String key) {
        final String[] returnName = new String[1];
        DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Profiles").child(key).child("Name");
        final CountDownLatch latch = new CountDownLatch(1);
        ref.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for (DataSnapshot datas : dataSnapshot.getChildren()) {
                    String userResult = datas.getKey();
                    if (userResult != null) {
                        returnName[0] = dataSnapshot.getValue().toString();
                        String temp = dataSnapshot.getValue().toString();
                        Toast.makeText(getBaseContext(), "Step 1: " + temp, Toast.LENGTH_SHORT).show();
                        Toast.makeText(getBaseContext(), "Step 2: " + returnName[0], Toast.LENGTH_SHORT).show();
                        latch.countDown();
                    }
                }
                latch.countDown();
            }
    
            @Override
            public void onCancelled(DatabaseError databaseError) {
    
            }
        });
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return returnName[0].toString();
    }
    

    虽然它解决了你的问题,但它不是一个好的解决方案