使用SwingWorker在jTable中动态加载大数据

时间:2017-03-23 07:28:40

标签: java swing file-io jtable swingworker

在Netbeans中,我正在尝试创建一个桌面应用程序,其UI如下所示:

enter image description here

我正在通过Java代码执行“adb logcat命令”,该代码在几秒钟内加载了1000行日志。我打算通过NetBeans中的jTable显示所有这些信息。

使用参数:adb logcat -t 100 - >我现在只将日志限制为100行。 但是,对于1000行或在删除对行数的限制时,applet变得无响应(或卡在process()方法中)。

我不确定我是否在代码中正确实现了SwingWorker线程。我正在寻找有关如何改进代码以动态加载大量数据的建议,而不会让applet变得无法响应。

以下是applet实现的代码...包含2个函数:

  1. 从applet的init()方法调用的viewLogs()。
  2. SwingWorker实现。

        public void viewLogs() throws IOException {
    
        String[] command = {"CMD","/C", "adb logcat -t 100"};
        ProcessBuilder probuilder = new ProcessBuilder( command );
        probuilder.directory(new File("c:\\Users\\k.garg\\Desktop\\"));
        Process process = probuilder.start();
    
        InputStream is = process.getInputStream();      
        InputStreamReader isr = new InputStreamReader(is);
        br = new BufferedReader(isr);
    
        DefaultTableModel model = (DefaultTableModel)jTable1.getModel();
        worker.execute();
    
        try {
            int exitVal = process.waitFor();
            System.out.println("exitVal = " + exitVal);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public class TableSwingWorker extends SwingWorker<DefaultTableModel, Object[]>{
    private DefaultTableModel tableModel;
    public TableSwingWorker(DefaultTableModel tableModel){
        this.tableModel = tableModel;
    }
    
    @Override
    protected DefaultTableModel doInBackground() throws Exception {
        Thread.sleep(2000); //added for initial UI to load
        System.out.println("Start populating");
        String line, date, time, loglevel, PID, TID, tag, message="";
        String log;
        int count = 0;
        while ((log = br.readLine()) != null) {
            count++;
    
            String[] splitLog = log.trim().split("\\s+");
            line = Integer.toString(count);
            date = splitLog[0];
            time = splitLog[1];
            PID = splitLog[2];
            TID = splitLog[3];
            loglevel = splitLog[4];
            tag = splitLog[5];
            for(int i=6; i<splitLog.length;i++){
                message += splitLog[i];
            }
            publish(new Object[]{line, date, time, PID, TID, loglevel, tag, message});
        }
        return tableModel;
    }
    
    @Override
    protected void process(List<Object[]> chunks) {
        System.out.println("Adding " + chunks.size() + " rows");
        for(Object[] row: chunks)
            tableModel.insertRow(0,row);
    }
    

    }

1 个答案:

答案 0 :(得分:2)

关键问题是......

try {
    int exitVal = process.waitFor();
    System.out.println("exitVal = " + exitVal);
} catch (InterruptedException e) {
    e.printStackTrace();
}

这阻止了事件调度线程,阻止在Process完成之前发生任何可能的更新,这有点违背了使用SwingWorker的目的。

您最好直接执行Process中的SwingWorker,例如......

public class TableSwingWorker extends SwingWorker<Integer, Object[]> {

    private DefaultTableModel tableModel;
    private int count;

    public TableSwingWorker(DefaultTableModel tableModel) {
        this.tableModel = tableModel;
    }

    @Override
    protected Integer doInBackground() throws Exception {
        count = 0;

        String[] command = {"CMD", "/C", "adb logcat -t 100"};
        ProcessBuilder probuilder = new ProcessBuilder(command);
        probuilder.directory(new File("c:\\Users\\k.garg\\Desktop\\"));
        Process process = probuilder.start();

        InputConsumer consumer = new InputConsumer(process.getInputStream());
        consumer.start();

        int result = process.waitFor();
        consumer.join();

        return result;
    }

    @Override
    protected void process(List<Object[]> chunks) {
        System.out.println("Adding " + chunks.size() + " rows");
        for (Object[] row : chunks) {
            tableModel.insertRow(0, row);
        }
    }

    protected void processOutput(String text) {
            count++;

            String[] splitLog = text.trim().split("\\s+");
            String line = Integer.toString(count);
            String date = splitLog[0];
            String time = splitLog[1];
            String PID = splitLog[2];
            String TID = splitLog[3];
            String loglevel = splitLog[4];
            String tag = splitLog[5];

            StringBuilder message = new StringBuilder(64);
            for (int i = 6; i < splitLog.length; i++) {
                message.append(splitLog[i]);
            }
            publish(new Object[]{line, date, time, PID, TID, loglevel, tag, message});
    }

    public class InputConsumer extends Thread {

        private InputStream is;

        public InputConsumer(InputStream is) {
            this.is = is;
            start();
        }

        @Override
        public void run() {
            try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
                String text = null;
                while ((text = br.readLine()) != null) {
                    processOutput(text);
                }
            } catch (IOException exp) {
                exp.printStackTrace();
            }
        }
    }
}

好吧,这可能看起来有点重&#34;但它做了两件重要的事情:

  1. 将关闭过程的InputStream加载到另一个Thread,这样我们就可以......
  2. waitFor要退出的流程,以便我们获得退出值,这可用于诊断为什么某些人不时不工作
  3. 其他观察