Android - 即使使用 .reset(),ObjectInputStream 也会继续读取先前的值

Posted

技术标签:

【中文标题】Android - 即使使用 .reset(),ObjectInputStream 也会继续读取先前的值【英文标题】:Android - ObjectInputStream keeps on reading the previous value even with .reset() 【发布时间】:2013-05-04 09:18:12 【问题描述】:

我正在构建一个用于在两部 android 手机之间发送文件的应用程序,现在我有一个 ListActivity 可以检索 sdcard 并列出文件,当 ListActivity 第一次在两台设备上启动时,会设置一个 ServerSocket 并使用 @987654322 进行侦听@...

这个线程在 ListActivity 启动时启动:

ReceiveFileSendRequestThread ReceiveFileSendRequestThread = new ReceiveFileSendRequestThread();
ReceiveFileSendRequestThread.start();

这是完整的线程类:

static public class ReceiveFileSendRequestThread extends Thread 
    public void run() 
        ServerSocket serverSocket;
        try 
            serverSocket = new ServerSocket(6789, 200);
            connectionServ = serverSocket.accept();
            requestFileInServer = new ObjectInputStream(
                    connectionServ.getInputStream());
            requestFileString = (String) requestFileInServer.readObject();

            handler.post(new AcceptFileSendAlertDialogRunnable());

            while (okToSend == null) 

            

            if (okToSend == true) 
                requestFileOutServer = new ObjectOutputStream(
                        connectionServ.getOutputStream());
                requestFileOutServer.writeObject("oktosend");
                requestFileOutServer.flush();
                serverSocket.close(); // // Receive File

             else if (okToSend == false) 
                requestFileOutServer = new ObjectOutputStream(
                        connectionServ.getOutputStream());
                requestFileOutServer.reset();
                requestFileOutServer.writeObject("notosend");
                requestFileOutServer.flush();
                serverSocket.close();

                ReceiveFileSendRequestThread ReceiveFileSendRequestThread = new ReceiveFileSendRequestThread();
                ReceiveFileSendRequestThread.start();
            

         catch (IOException e) 
            Log.d("Connection Error:", "Error binding port!");
            e.printStackTrace();
         catch (ClassNotFoundException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        

    

当 onLongClick 一个项目(发送文件)时,以下线程启动:

public boolean onItemLongClick(AdapterView<?> parentView, View childView,
        int position, long id) 
    // TODO Auto-generated method stub

    fileClickedName = (((TextView) childView).getText()).toString();
    fileClickedPath = file.toString() + "/" + fileClickedName;
    fileClickedFile = new File(fileClickedPath);

    SendFileThread SendFileThread = new SendFileThread();
    SendFileThread.start();

    return true;

发送文件线程:

static public class SendFileThread extends Thread 
    public void run() 
        Socket socket = new Socket();
        try 
            socket.connect(new InetSocketAddress(sharedIp, 6789), 200);
            requestFileOutClient = new ObjectOutputStream(
                    socket.getOutputStream());
            requestFileOutClient.writeObject(fileClickedName);
            requestFileOutClient.flush();

            requestFileInClient = new ObjectInputStream(
                    socket.getInputStream());
            toSendOrNot = (String) requestFileInClient.readObject();
            if (toSendOrNot.equals("oktosend")) 
                socket.close();
             else if (toSendOrNot.equals("notosend")) 
                socket.close();
                ReceiveFileSendRequestThread ReceiveFileSendRequestThread = new ReceiveFileSendRequestThread();
                ReceiveFileSendRequestThread.start();
                handler.post(new ClientFileSendAlertDialogRunnable());
            

            // //

         catch (IOException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
         catch (ClassNotFoundException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        
    

现在,当我启动 ListActivity 并 longClick 一个项目时,文件名被发送到第二台设备,第二台设备弹出一个 alertDialog 询问用户是否接受文件,(接受文件仍然现在还没有准备好)如果用户按下 CANCEL(在 ReceiveFileSendRequestThread 上)一个字符串被发送到第一个设备"notosend",第一个用户接收到字符串"notosend" 并且根据该线程关闭套接字并重新调用如果他想发送另一个文件,线程会监听第二个对等方,并弹出一个 alertDialog 告诉第一个用户您的文件被拒绝接收...>>>>这完全可行>>>>但是当第一个设备尝试发送另一个文件(再次长按文件 [列表中的项目])第二个用户成功接收第一个用户选择的新文件名,如果接受或取消,则会弹出 alertDialog 但第一个用户收到文件发送被拒绝......没有第二个d 用户按下取消按钮!!! ...我不知道为什么toSendOrNot = (String) requestFileInClient.readObject(); 继续采用以前的值,甚至没有等待第二个设备写入新对象。

如果有人可以帮助我,我将不胜感激,非常感谢。

【问题讨论】:

我也有这个问题..我读到 ObjectInputStream 和 ObjectOutputStream 有一个缓存内存..重置方法应该清除缓存,所以新数据将通过它..在我的情况下它有效但是当我发送一条新消息时,它会重复该消息..这是我的帖子..但没有人回答..也许那里的代码会给你一些关于如何解决你的问题的想法,***.com/questions/16318526/… @Elior ,感谢您的贡献,我跟踪了您的代码,但不幸的是没有任何帮助...关于缓存,我也读过它,可以使用以下方法重置:.reset()其主要目的是:重置流的状态并避免循环引用,我所做的方式应该是有效的,但没有机会......正在努力,但到目前为止我没有找到解决方案。 这里有太多无法运行的代码。将其简化为独立的测试用例。该过程可能会消除错误,这本身就是有益的。我注意到您在ReceiveFileSendRequestThread 中的每次发送都创建了一个新的ObjectOutputStream。仅此一项就可能导致问题。在套接字的整个生命周期中,两端都必须使用相同的 ObjectInput/OutputStreams @Elior ,我认为你必须为你的变量做一些清理工作。 @EJP ,现在它运行良好,感谢您的建议 > 我已经编辑了我的代码,所以它只有一个 ObjectInputStream, ObjectOutputStream 用于套接字的生命周期。 :D 【参考方案1】:

经过几个小时的调试>>>我终于找到了错误! 在线程ReceiveFileSendRequestThread() 中,Boolean 变量okToSend 在第一次接收来自第二个设备的请求时为空,当第二个设备取消请求时,oKtoSend 将设置为notosend,因此每当第二个设备尝试要发送另一个文件,变量okToSend 将始终具有先前分配的值。所以我只是在while 循环之前添加了okToSend = null;,现在可以正常工作了。

【讨论】:

但是当你发送一个新数据时,它是重复的吗?我的意思是,在我的情况下,当我发送第一条消息时,我只发送一次,但客户端设备读取了两次,而当我发送第二条消息时,客户端读取了四次..

以上是关于Android - 即使使用 .reset(),ObjectInputStream 也会继续读取先前的值的主要内容,如果未能解决你的问题,请参考以下文章

Office365 - 如何在Android手机中reset OneDrive

FlinkHttpClient 报错 I/O SocketException caught when processing request to Connection Reset

git reset 之后的恢复

android O中的onMessageReceived在后台应用时未调用

Android 电池使用情况分析

github总结--关于git reset --hard这个命令的惨痛教训