igraph цветные вершины с коэффициентом [дубликат]

Это классическая проблема с асинхронными веб-интерфейсами. Вы не можете вернуть то, что еще не загружено. Другими словами, вы не можете просто создать глобальную переменную и использовать ее вне метода onDataChange(), потому что она всегда будет null. Это происходит потому, что метод onDataChange() называется асинхронным.

Но не только Firebase Realtime Database загружает данные асинхронно, почти все современные другие сети API, так как это может занять некоторое время. Поэтому вместо того, чтобы ждать данных (что может привести к невосприимчивым диалоговым окнам приложений для ваших пользователей), ваш основной код приложения продолжается, пока данные загружаются во вторичный поток. Затем, когда данные доступны, вызывается метод onDataChange () и может использовать данные. Другими словами, к тому времени, когда метод onDataChange() называется, ваши данные еще не загружены.

Давайте возьмем пример, разместив несколько кодов журнала в коде, чтобы более четко видеть, что происходит.

private String getUserName(String uid) {
    Log.d("TAG", "Before attaching the listener!");
    databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            // How to return this value?
            dataSnapshot.getValue(String.class);
            Log.d("TAG", "Inside onDataChange() method!");
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {}
    });
    Log.d("TAG", "After attaching the listener!");
}

Если мы запустим этот код, выход wil будет:

Перед присоединением слушателя!

После присоединения слушателя!

Внутри метода onDataChange ()!

blockquote>

Это, вероятно, не то, что вы ожидали, но оно точно объясняет, почему ваши данные null при возврате.

Первоначальный ответ для большинства разработчиков заключается в том, чтобы попытаться «исправить» это asynchronous behavior, что я лично рекомендую против этого. Интернет является асинхронным, и чем скорее вы примете это, тем скорее вы сможете узнать, как стать продуктивным с помощью современных веб-API.

Я нашел проще всего пересмотреть проблемы для этой асинхронной парадигмы. Вместо того, чтобы говорить «Сначала получить данные, а затем занести в журнал», я создаю проблему как «Начать получать данные. Когда данные загружаются, запишите их». Это означает, что любой код, который требует данных, должен быть внутри метода onDataChange() или вызван изнутри, например:

databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        // How to return this value?
        if(dataSnapshot != null) {
            System.out.println(dataSnapshot.getValue(String.class));
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {}
});

Если вы хотите использовать это снаружи, есть другой подход. Вам нужно создать свой собственный обратный вызов, чтобы ждать, пока Firebase вернет вам данные. Для этого сначала нужно создать interface следующим образом:

public interface MyCallback {
    void onCallback(String value);
}

Затем вам нужно создать метод, который фактически получает данные из базы данных. Этот метод должен выглядеть так:

public void readData(MyCallback myCallback) {
    databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            String value = dataSnapshot.getValue(String.class);
            myCallback.onCallback(value);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {}
    });
}

. В конце просто просто вызовите метод readData() и передайте экземпляр интерфейса MyCallback в качестве аргумента везде, где вам это нужно:

readData(new MyCallback() {
    @Override
    public void onCallback(String value) {
        Log.d("TAG", value);
    }
});

Это единственный способ, которым вы можете использовать это значение вне метода onDataChange(). Для получения дополнительной информации вы также можете посмотреть это видео .

9
задан Salvador Dali 14 April 2013 в 14:58
поделиться

2 ответа

Самый простой способ - создать граф, содержащий все метаданные, а затем igraph позаботится об остальном. Например,

library(igraph)

answers <- read.table(textConnection(
   "  Player Q1_I1                                                             
    1      k     1                                                             
    2      l     0                                                             
    3      n     1                                                             
    4      m     0                                                             
"))

topology <- read.table(textConnection(
   "  Node.1 Node.2                                                            
    1      k      l                                                            
    2      l      k                                                            
    3      l      m                                                            
    4      m      l                                                            
    5      l      n                                                            
    6      n      l                                                            
    7      n      k                                                            
    8      k      n                                                            
 "))

g2 <- graph.data.frame(topology, vertices=answers, directed=FALSE)
g <- simplify(g2)
V(g)$color <- ifelse(V(g)$Q1_I1 == 1, "lightblue", "orange")

plot(g)

plot [/g0]

Но на самом деле, если вы не включаете каждое ребро в обоих направлениях в своей таблице данных, тогда вы даже не необходимо упростить.

16
ответ дан Gabor Csardi 23 August 2018 в 20:29
поделиться

Проблема в том, что граф сортируется после simplify, а вектор ответов - нет. Возможно, вам будет проще, но я просто сортирую вашу таблицу ответов: answers <-answers[order(answers[,1]),] перед установкой V(g)$color <- ifelse(answers[V(g), 2] == 1, "blue", "red").

Вы можете видеть, что ваш график отсортирован с помощью get.data.frame(g, what="vertices")

Кроме того, вы могли бы match имена get.data.frame (обратите внимание, что я дважды создаю g. По какой-то причине get.data.frame не играет хорошо с simplify.

answers <- read.csv("c:/answers2.csv",header=T)
data1<-read.csv('c:/edges2.csv')
data2<-graph.data.frame(data1, directed=FALSE)
g<-simplify(data2)
ordered.vertices <-get.data.frame(g, what="vertices")
g<-simplify(data2)
V(g)$color <- ifelse(answers[match(answers[,1],ordered.vertices$name), 2] == 1, "blue", "red")
plot(g, layout=layout.fruchterman.reingold, vertex.color=V(g)$color)

enter image description here [/g0]

4
ответ дан Pierre Lapointe 23 August 2018 в 20:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: