마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

도와주세요...ㅠㅠ대용량 text를 runnable을 이용하여 textview에 write 하기

0 추천

안녕하세요. 초보 개발자 입니다.

현재 while 문을 이용하여 shell 에서 http패킷을 BufferedReader.readline 으로 나온 Text를 Textview에 표시하는 프로그램 개발중 입니다.

여기서 문제가 앱을 실행시키고 종료시키지 않고 홈버튼을 누르고 내려놓은 다음에 웹을 실행시켜 패킷을 수집한 후 다시 앱을 실행시키면 Text의 양이 많을수록 검은화면에서 굉장히 오랜시간을 기다려야 앱이 실행되면서 텍스트가 보입니다.

텍스트가 logcat 에서는 빠르게 올라가기 때문에 많은 양임을 알수가 있는데

그 양이 한번에 텍스트뷰에 그리려다 보니까 시간이 오래 걸리는것으로 생각됩니다.

   TextView mTcptv;
    Handler handler;

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);



        mTcptv = (TextView) findViewById(R.id.log_tv);
        mTcptv.setMovementMethod(new ScrollingMovementMethod());

        startWrite();

}

private void startWrite()
    {
        thread = new Thread(new Runnable()
        {
            public void run()
            {
                writePacket();
            }
        });
        thread.start();
    }

 private void writePacket(){
        String temp = new String();
        Message msg;


        try {
            ......
                            중간 생략
                                                         .......


            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            FileOutputStream fos = new FileOutputStream(dumpedFile);

            while (!thread.interrupted()) {

                temp = reader.readLine();

                if (temp != null) {
                    Log.e("READER", new String(temp));
                    fos.write(temp.getBytes());

                    if (temp.matches("\r"))
                        fos.write("\r\n".getBytes());

                    msg = handler.obtainMessage();
                    msg.obj = (Object) temp;
                    handler.sendMessage(msg);



                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            handler = new Handler() {
                                public void handleMessage(Message msg) {
                                    super.handleMessage(msg);
                                    mTcptv.append((String) msg.obj + "\n");

                                }
                            };
                        }
                    });
                }
            }

        } catch (Exception e) {
            Log.e("Process Manager", "Unable to execute top command");
            e.printStackTrace();

        }



    }

 

위 코드입니다.. 

해결 하고 싶은것은 이 앱을 홈버튼으로 밑으로 내려놓고 패킷을 수집한후에 앱이 돌아가도 

오랜시간을 기다리지 않고 바로 텍스트가 뜨게 하고 싶습니다.

코드 상에서 RunOnUiThread 부분의 코드를 변경해야 할 것 같은데 어떻게 해야 해결되는지 알고싶습니다..

아마 그러기 위해서는 화면이 내려간 상태에서도 계속적으로 텍스트뷰에 쓰고 있어야 할텐데 

방법을 모르겠습니다.. 위에 코드도 많이 생각해서 runOnUiThread 를 사용한 것입니다..

다른 방법이 있다면 무지한 저에게 알려주시면 감사하겠습니다.

헐잘생겼다 (570 포인트) 님이 2016년 10월 11일 질문
헐잘생겼다님이 2016년 10월 11일 수정

1개의 답변

0 추천
핸들러를 중복으로 사용하셨네요.

runOnUiThread 함수 자체가 메인 스레드안에서 동작하도록 핸들러를 품고 있습니다.

runOnUiThread 함수 안에 있는 핸들러를 없애시고 안에 있는 append 함수 사용하는 부분을 끄집어 내어 보세요.

 

그리고 ANR이 발생하는 부분 관련해서 보면 통신 스트림이 아니라 파일 스트림이네요.

로컬에서 읽는거라 지연시간이 거의 없다고 봐도 무방한데 이런 경우는 쓰레드를 사용한다고 하여도 버벅일 수가 있습니다. 간단하게 수정을 하고 싶으신거면 while루프에 sleep값을 일부러 줘보세요. 속도는 조금 걸리지만 ANR부분은 조금 개선 하실 수 있을겁니다.

또 다른 방법으로 스트림 읽는 작업을 쓰레드가 아닌 IntentService에서 작업하시고 읽은 라인을 Broadcast 하여 Activity에서는 BroadcastReceiver에서 이를 받아 텍스트뷰에 쓰는 방법이 있습니다. 홈화면으로 갔을때도 동작하여야 한다고 하셨으니 일반 쓰레드에서 하는것보단 이 방법이 안정적일 수가 잇습니다. 그리고 Broadcast할때 그냥 Broadcast 하지 마시고 PendingIntent를 통해서 하셔야 버벅임을 줄일 수 있습니다.
Development Guy (70,570 포인트) 님이 2016년 10월 11일 답변
네 감사합니다. 한번 해보겠습니다.
Service로 하였는데도 여전히 ANR이 발생하고 있습니다.
MainActivity에 BroadcastReceiver 클래스를 생성하여 intent getExtra 로 값을 가져와 setText 를 하고 있는데...
이건 홈화면으로 갔을때 setText를 하고있는게 아닌건가요?
...