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

리스트뷰,어댑터에서 메소드를 추가하니 NullPointerException이 뜹니다.

0 추천

안녕하세요? 저는 게임의 저장/불러오기 기능을 만들어보고 싶어서 어댑터,리스트뷰로 저장슬롯을 만들고

직렬화를 통해 저장하고 불러오는 기능을 만들고 있습니다.

그 중에서 저장을 하면 저장슬롯(리스트뷰 아이템)에 저장된 정보가 출력되는 기능을 만들고 있습니다.

껐다가 재시작을 해도 그대로 남을 수 있게요.

다른 텍스트들은 직렬화로 저장파일을 만들어서 불러오니 원하는대로 출력이 되었습니다.

그런데 Bitmap(저장 당시의 스크린샷 용도로 쓰입니다)의 경우엔 Serializable을 구현하지 않으므로 ByteArray로 바꾼 다음 저장하고, 저장한 ByteArray를 다시 Bitmap으로 바꿔서 사용하려고 했습니다.

그런데 저장한 ByteArray를 다루는 메소드만 선언하면 NullPointException 오류가 생기면서 앱이 강제로 종료됩니다. 단지 메소드 하나를 추가했을 뿐인데도 그 메소드만 코드에 들어갔다 하면 강제로 종료되니 도저히 영문을 알 수가 없어서 답답합니다... 이런경우에는 무슨 키워드로 검색을 해야 하는지.. 

오류코드는 질문게시글 글자제한이 너무 짧아서 댓글에 작성하겠습니다.

사용된 어댑터 클래스입니다.

 

public class BaseAdapterEx extends BaseAdapter {


    Context             mContext    = null;
    ArrayList<SaveData> mData       = null;
    LayoutInflater      mLayoutInflater = null;


    public BaseAdapterEx(Context context, ArrayList<SaveData> data)
    {
        mContext = context;
        mData = data;
        mLayoutInflater = LayoutInflater.from(mContext);

    }

    @Override
    public int getCount(){

        return mData.size();

    }

    @Override
    public long getItemId(int position){

        return position;

    }

    @Override
    public SaveData getItem(int position){

        return mData.get(position);
    }

    @Override
    public View getView(int position,
                        View convertView,
                        ViewGroup parent)
    {
        View itemLayout = mLayoutInflater.inflate(R.layout.saveload_listview_item,null);

        TextView saveOrder = (TextView) itemLayout.findViewById(R.id.saveload_order);
        TextView saveWords = (TextView) itemLayout.findViewById(R.id.saveload_words);
        ImageView saveImage = (ImageView) itemLayout.findViewById(R.id.saveload_image);


        saveOrder.setText(mData.get(position).getSaveOrder());
        saveWords.setText(mData.get(position).getSaveWord());
        saveImage.setImageBitmap(mData.get(position).getScreenShot());
       // saveImage.setImageBitmap(mData.get(position).getEncodeScreenShot()); 그래서 이것또한 사용하지 못하고 있습니다.

        return itemLayout;

    }



}

저장 데이터 보관용도로 사용하는 SaveData(Arraylist로 사용) 클래스입니다.

 

public class SaveData implements Serializable{

    private int keyNum;
    private int stageNum;
    transient private Bitmap screenShot; //세이브상황에서의 스크린샷 한장
    private String saveOrder; //세이브 슬롯 넘버
    private String saveWord; // 세이브 상황 시의 진행중이던 대사
    private byte[] encodeScreenShot;



    public void setKeyNum(int keyNum){

        this.keyNum = keyNum;

    }
    public void setStageNum(int stageNum){

        this.stageNum = stageNum;
    }

    public void setScreenShot(Bitmap screenShot) {this.screenShot = screenShot;}
    public void setSaveOrder(String saveOrder){
        this.saveOrder = saveOrder;
    }
    public void setSaveWord(String saveWord){
        this.saveWord = saveWord;
    }
    public void setEncodeScreenShot(byte[] encodeScreenShot){this.encodeScreenShot = encodeScreenShot;}


    public Bitmap getScreenShot(){
        return screenShot;
    }

    //public Bitmap getEncotdeScreenShot(){return BitmapFactory.decodeByteArray(encodeScreenShot,0,encodeScreenShot.length);}
    // 이 부분 주석만 풀면 오류가 납니다.
    /*  이 메소드를 사용하는 것도 아니고 이렇게 만들어만 놓은 상태로 둬도 오류가 생기며 앱이 꺼집니다. */
    /* 또한, 저 메소드에 return null;이나 return screenShot; 등의 다른 코드를 넣어도 똑같이 꺼집니다.. 그냥 얘가 주석만 풀리면 문제가 생기는것 같습니다.*/

    public String getSaveOrder(){
        return saveOrder;
    }
    public String getSaveWord(){
        return saveWord;
    }



}

 

그리고 오류가 생긴 부분의 (SaveLoad.java) refresh() 메소드입니다.

 

public void refresh(){
    mAdapter = new BaseAdapterEx(this,saveData);
    mListView.setAdapter(mAdapter);
    mAdapter.notifyDataSetChanged();

}

제 코드는 SaveData객체를 직렬화로 불러와서 기존 SaveData객체를 교체하고, 어댑터를 새로 선언합니다.

(교체한 SaveData 객체로 적용하기 위해)

리스트뷰를 새로고침하기 위해 사용하는 방법인데 제대로 된 방법인지는 잘 모르겠습니다.

 

오류내역을 보면 어댑터의 getCount() 메소드에서부터 Null에 관련된 문제가 있는것같은데,..

 

해결방법은 둘째치고서라도 원인이라도 알고싶은 마음입니다.

감사합니다.

//8000자 제한으로 연관이 멀어보이는 오류내용이나 import내용은 지웠습니다.

//오류코드는 질문게시글 글자제한이 너무 짧아서 댓글에 작성하겠습니다.

앱 내부화면입니다. 이런느낌입니다.

ACA (220 포인트) 님이 2017년 1월 13일 질문
01-13 22:37:46.920 17340-17340/com.novel.aca.visualnovelproject E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                  Process: com.novel.aca.visualnovelproject, PID: 17340
                                                                                  java.lang.RuntimeException: Unable to start activity ComponentInfo{com.novel.aca.visualnovelproject/com.novel.aca.visualnovelproject.SaveLoad}: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
                                                                                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3254)
                                                                                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350)
                                                                                      at android.app.ActivityThread.access$1100(ActivityThread.java:222)
                                                                                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795)
                                                                                      at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                      at android.os.Looper.loop(Looper.java:158)
                                                                                      at android.app.ActivityThread.main(ActivityThread.java:7229)
                                                                                      at java.lang.reflect.Method.invoke(Native Method)
                                                                                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                                                                                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
                                                                                   Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
                                                                                      at com.novel.aca.visualnovelproject.BaseAdapterEx.getCount(BaseAdapterEx.java:39)
                                                                                      at android.widget.ListView.setAdapter(ListView.java:508)
                                                                                      at com.novel.aca.visualnovelproject.SaveLoad.refresh(SaveLoad.java:67)
                                                                                      at com.novel.aca.visualnovelproject.SaveLoad.onCreate(SaveLoad.java:117)
                                                                                      at android.app.Activity.performCreate(Activity.java:6876)
                                                                                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1135)
                                                                                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3207)
                                                                                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350) 
                                                                                      at android.app.ActivityThread.access$1100(ActivityThread.java:222) 
                                                                                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795) 
                                                                                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                                      at android.os.Looper.loop(Looper.java:158) 
                                                                                      at android.app.ActivityThread.main(ActivityThread.java:7229) 
                                                                                      at java.lang.reflect.Method.invoke(Native Method) 
                                                                                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
                                                                                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 

1개의 답변

0 추천
refresh()의 mAdapter = new BaseAdapterEx(this,saveData); 코드에서 두번째 인자인 saveData가 null인것 같네요.

본문에 saveData를 생성하는 부분의 코드가 없어서 정확한 원인을 찾기는 어렵네요.
isul (7,920 포인트) 님이 2017년 1월 14일 답변
감사합니다! 정말 말끔하게 해결되었습니다.
원인은 새로운 메소드를 만든 후에 직렬화 한 저장파일을 불러올 때, 기존의 객체와 새로 메소드를 추가한 객체의 serialVersionUID가 서로 맞지 않아서
예외가 발생하면서 saveData가 생성되지 않아 null이 된 거였습니다.
덕분에 진짜 개운하게 해결한 것 같아 감사합니다.

혹시 제 코드에서 saveData가 null이 되었다는 걸 어떻게 알 수 있는지 추가로 써 주실수 있으신가요?
아래 에러 로그의 첫 라인에 보면 "NullPointerException"이 보이고, ArrayList.size() on a null object reference이라고 되어 있죠.. 널인 객체(ArrayList 타입)의 size()를 호출하여 발생되었다고하네요.
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference

그리고, 로그 중 제일 먼저 나오는 "만드신 패키지명"(com.novel.aca.visualnovelproject)을 찾아보면 아래처럼 나오죠.
com.novel.aca.visualnovelproject.BaseAdapterEx.getCount(BaseAdapterEx.java:39)
                                                                                      at android.widget.ListView.setAdapter(ListView.java:508)
                                                                                      at com.novel.aca.visualnovelproject.SaveLoad.refresh(SaveLoad.java:67)

BaseAdapterEx.java의 39번째 라인인 getCount()의 return mData.size(); 부분에서 에러가 발생했다고 알려주죠.
getCount()에서 size()를 사용하는 객체는 mData(ArrayList 타입)이고, 그 mData는 BaseAdapterEx의 생성자에서 두번째 인자이죠.
getCount()를 호출한 부분이 SaveLoad.java의 67번째 라인인데 올려주신 소스에는 라인번호가 없어서 정확히 알 수 없지만 위에서 어댑터 생성 코드에서 두 번째 인자인 saveData가 null이라는 걸 알 수 있습니다.

로그 보실 때는 항상 본인이 직접만든 패키지명부터 찾아서 거기서부터 보세요.
...