android studio 2.0 android monitor 버그..
사용자 스레드에서도 Handler(UI쓰레드) 생성할 수 있다.
사용자 스레드를 만들고 그 안에서 UI변경 하려고 하면 다음과 오류가 뜬다.
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
쉽게 말해 안드로이드는 UI를 메인스레드에서 관리하는데 지금 니가 만든 사용자 스레드에서 UI를 건들고 있다. 이건 위험하다. 이런 얘기다.
그래서 사용자 스레드에서 바로 하지 않고 Handler 를 사용해서 UI 건드니깐 또 이런 오류가 뜬다.
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
Handler는 MainThread를 사용하는거 아니였나?? ㅡ,,ㅡ?
android.os.Handler handler = new android.os.Handler(Looper.getMainLooper());
위와 같이 만들어주면 이제 오류 메세지를 피할 수 있다.
Handler는 Looper를 통해 스레드의 MessageQueue에 메세지를 전달 하는 역활을 하는데, 우리가 만든 사용자 스레드에는 Looper와 MessageQueue가 없다.
그래서 오류 메세지를 나왔던 것이고, 위와 같이 Looper.getMainLooper() 함수를 통해 MainThread의 Looper를 받아서 만들면 오류를 피할 수 있는 것 이다.
안드로이드 RecyclerView 스크롤 감지
onScrollStateChanged함수는 기존에 onScroll 함수가 스크롤 할 때마다 호출되어 반응성이 좋게 코드를 만들 수도 있겠지만, 빈번한 호출로 어플이 버벅일수도 있었다. 그러한 점을 고쳐 newState로 들어오는 스크롤 상태변수는 상태가 변할 때 마다 딱 1번만 호출되어 값을 넘겨준다.
SCROLL_STATE_SETTLING
상태는 위든 아래든 스크롤이 끝까지 갔음을 의미한다.
SCROLL_STATE_IDLE
상태는 현재 스크롤을 하지 않는 상태, SCROLL_STATE_DRAGGING
스크롤을 하고 있는 상태이다.
onScrolled함수의 dx, dy 변수는 각자 수직 수평으로 스크롤이 얼마나 되었는지 그 양을 뜻한다. 스크롤 위치가 아니다, 절대.
dy가 음수 값이면 현재 위치를 0 기준 잡고 위로 스크롤 했다는 뜻이고, dy가 양수면 아래로 스크롤 했다는 뜻이다.
'android' 카테고리의 다른 글
네트워크 상태 체크 하기 (1) | 2016.04.26 |
---|---|
UI Thread 사용법 (0) | 2016.04.24 |
ListView를 대체할 새로운 컴포넌트 Recyclerview (0) | 2016.04.24 |
네트워크 상태 체크 하기
Android를 개발하다 보면, 네트워크 통신 전에 꼭 해야 할 것이 있는데 이것이 바로 현재 단말기가 mobile network or Wifi에 연결되어 있는지 확인 후, 통신을 시도하게 된다.
오랜만에 코딩 하고 있는지라, api 23 부터 기존 아래의 코드는 deprecated 되었다.
1: ConnectivityManager manager = (ConnectivityManager) MyApplication.mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
2: NetworkInfo mobile = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
3: NetworkInfo wifi = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
4:
5: if (mobile.isConnected() || wifi.isConnected()) {
6:
7:
8: } else {
9: // WIFI, 3G 어느곳에도 연결되지 않았을때
10:
11: }
새로운 방식은 아래와 같다.
1: ConnectivityManager cm = (ConnectivityManager) MyApplication.mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
2: NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
3: if (activeNetwork != null) {
4:
5: if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI && activeNetwork.isConnectedOrConnecting()) {
6: // wifi 연결중
7:
8: } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE && activeNetwork.isConnectedOrConnecting()) {
9: // 모바일 네트워크 연결중
10:
11: }
12: else
13: {
14: // 네트워크 오프라인 상태.
15: }
16: } else {
17: // 네트워크 null.. 모뎀이 없는 경우??
18: }
흠.. 별로 달라진 것이 없는 것 같지만, 이제 어떤 통신인지 구별도 가능하게 되었다..
MyApplication.mContext는 내가 만든 context를 저장하기 위한 전역 변수 역할을 하는 클래스이다.. 필자는 어디서든 쓸 수 있도록 저렇게 쓴다.
다른 분들은 그 자리에는 자신이 만든 main Activity의 context를 넣자.
'android' 카테고리의 다른 글
안드로이드 RecyclerView 스크롤 감지 (0) | 2016.04.26 |
---|---|
UI Thread 사용법 (0) | 2016.04.24 |
ListView를 대체할 새로운 컴포넌트 Recyclerview (0) | 2016.04.24 |
UI Thread 사용법
안드로이드는 크게 사용자가 만든 쓰레드와 UI를 담당하는 MainThread(UI Thread)가 있는데, Activity내부에서 쓰여진 코드들은 모두
UI쓰레드에서 실행된다.
그래서 쓰레드를 따로 쓰지 않고, 연산이 오래 걸릴 가능성이 있는 network 소켓을 사용한 통신을 한다 던지, file I/O 작업을 하게 되면
오류가 나며, 강제 종료 되게끔 되어있다.
왜 그런 것 일까? 우리가 안드로이드 입장이 되어 보면 당연하다. 만일 UI 쓰레드에서 네트워크 통신을 하면, 통신 하는 동안에는 UI
작업을 못하니깐, 말 그대로 화면이 멈출 것이다.
사용자가 화면을 터치해도 무반응일 것이며, 화면이 먹통이 되어버릴 것이다. 그래서 꼭 이런 작업들은 따로 사용자 스레드를 만들
어서 작업해주어야 한다.
사용법은 아래와 같다.
1: new Thread(new Runnable()
2: {
3: @Override
4: public void run()
5: {
6: //수행 할 작업 코드
7: }
8: }).start();
간단하다. But, 그런데 사용자 스레드 작업 중, UI를 변경(UI스레드에서 작업)하고 싶다면 어떻게 할까?
예를 들면 통신이 실패 해서 사용자에게 “통신이 상태가 좋지 않습니다” 라고 메세지를 띄우고 싶다면?
그럴 경우도 안드로이드는 친절히 방법을 마련해 놓았다.
아래와 같이 사용하면 된다.
1: MainActivity.runOnUiThread(new Runnable()
2: {
3: @Override
4: public void run()
5: {
6: //여기에 UI스레드에서 동작하게 하고 싶은 내용 입력
7: }
8: });
App 내에 자신이 정의한 메인엑티비티.runOnUiThread( )를 사용하면 된다. 제발 소스코드 복사 붙여 넣기 해서, “MainActivity선언이
안되어 있어요..” 라고 말도 안 되는 소리 하지 말자..
'android' 카테고리의 다른 글
안드로이드 RecyclerView 스크롤 감지 (0) | 2016.04.26 |
---|---|
네트워크 상태 체크 하기 (1) | 2016.04.26 |
ListView를 대체할 새로운 컴포넌트 Recyclerview (0) | 2016.04.24 |