回调监听器无法正常工作

时间:2017-06-08 12:50:21

标签: java android callback realm listener

我在我的应用中使用Object.freeze()。 我做一个异步请求来获取这样的对象:

package testbroadcastudp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;

/**
* @since 03-05-2017
* @author jsanchez
*/
public class UDPBroadcastToLantronixDevices {
    public static void main(String[] args){
        //Port 30718 for sent at Lantronix devices
        try (DatagramSocket serverSocket = new DatagramSocket(30718)) 
        {//30718 50000
            byte[] queryMsg = new byte[4];
            queryMsg[0] = (byte)0x00;
            queryMsg[1] = (byte)0x00;
            queryMsg[2] = (byte)0x00;
            queryMsg[3] = (byte)0xF6;//Dec 246
            String testByte = new String(queryMsg,StandardCharsets.ISO_8859_1);

            serverSocket.setBroadcast(true);
            DatagramPacket datagramPacket = new DatagramPacket(
                queryMsg,
                queryMsg.length,
                InetAddress.getByName("192.168.1.255"),//192.168.1.201
                30718
            );
            //Send broadcast
            serverSocket.send(datagramPacket);
            //Close Broadcast socket to close the 30718 port.
            serverSocket.close();
            //Start the listening from the server
            receive();
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static void receive(){
        //Port 30718 for listen Lantronix devices
        try (DatagramSocket clientSocket = new DatagramSocket(30718)) {
            byte[] buffer = new byte[4];

            // Set a timeout of 3000 ms to listen in the server side
            clientSocket.setSoTimeout(3000);
            while (true) {
                DatagramPacket datagramPacket = new DatagramPacket(buffer, 0,             buffer.length);

                /**
                * The receive method will wait for 3000 ms for data.
                * After that, the server will throw a timeout exception.
                */
                clientSocket.receive(datagramPacket);
                System.out.println("Listen on " + datagramPacket.getAddress() + " from " + datagramPacket.getData().toString() + " port " + datagramPacket.getPort());
                String receivedMessage = new String(datagramPacket.getData());
                //Decode to get the 0xF7 or '÷' in the byte[4] for a Lantronix Devices in the LAN
                receivedMessage = new String(datagramPacket.getData(), StandardCharsets.ISO_8859_1);
                System.out.println(receivedMessage);
            }
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("Timeout. Client is closing.");
        }
    }
}

听众类:

    public static void getMissions(final List<StatutMission> listStatus, final SListener<List<RMission>> listener) {

    final String[] statesCode = new String[listStatus.size()];

    for (int i = 0; i < listStatus.size(); i++) {
        statesCode[i] = listStatus.get(i).getStateCode();
    }


    final RealmResults<RMission> results = Realm.getDefaultInstance().where(RMission.class).in("state", statesCode).findAllAsync();
    results.addChangeListener(new RealmChangeListener<RealmResults<RMission>>() {
        @Override
        public void onChange(RealmResults<RMission> element) {

            Log.d(TAG, element.size() + " mission(s) found in database with states " + StringUtils.arrayToString(statesCode, ","));
            listener.onResponse(Realm.getDefaultInstance().copyFromRealm(element));
            results.removeChangeListener(this);

        }
    });

}

}

我在多台设备上测试了我的代码,但只在一台设备(三星平板电脑)上测试了这个问题。

问题代码:

public interface SListener<T> {

void onResponse(@Nullable T result);

有人可以帮我解决这个问题吗?

提前致谢。

1 个答案:

答案 0 :(得分:2)

1。)Realm.getDefaultInstance().where(...Realm.getDefaultInstance().copyFromRealm(...您正在打开永远无法关闭的Realm实例,请阅读the docs

2。)你没有保留RealmResults作为字段引用,因此终结器会在评估异步查询之前销毁它,因此不会调用回调,阅读文档herehere

  

来自 javadoc

     

注册更改侦听器不会阻止底层RealmResults被垃圾回收。 如果RealmResults被垃圾收集,则更改侦听器将停止被触发。为避免这种情况,请尽可能长时间保持强有力的参考,例如在类变量中。

public class MyActivity extends Activity {

    private RealmResults<Person> results; // Strong reference to keep listeners alive

    @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         results = realm.where(Person.class).findAllAsync();
         results.addChangeListener(new RealmChangeListener<RealmResults<Person>>() {
           @Override
           public void onChange(RealmResults<Person> persons) {
               // React to change
           }
       });
     }
     // remove change listeners, and close Realm in onDestroy()
 }

3.。)如果你 复制懒惰评估的RealmResults EEGERLY中的每一个懒惰评估元素,那么对于异步评估查询的所有麻烦都是没有意义的 ,所以你应该重新评估你的逻辑,特别是在你阅读the relevant docs on how Realm queries work之后。

  

所有提取(包括查询)在Realm中都是惰性的,数据永远不会被复制

由于数据永远不会被复制,因此您没有理由使用copyFromRealm()