Search code examples
javaandroidlayout-inflateroncreate

Error when Views are named before the onCreate() method has run


When running this code the application crashes instantly.

Error: java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{(...).MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Window$Callback android.view.Window.getCallback()' on a null object reference

Through research I was able to find out the cause of the crash is likely to be that I name two Views before the onCreate() method has run. I could name these Views within the onCreate() method and the following listeners but then the Views cannot be public, so they would be independent from each other which would prevent my App from working as intended. Does someone have any idea on how to prevent this problem without making these Views independent from each other?

MainActivity.java:

public class MainActivity extends AppCompatActivity {
    public ConstraintLayout constraintLayout = (ConstraintLayout) findViewById(R.id.constraint_layout0);
    LayoutInflater inflater = getLayoutInflater();
    public View rectimage3 = inflater.inflate(R.layout.my_rectview, constraintLayout, false);

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

        final ImageView rectimage = (ImageView) findViewById(R.id.rectimage);

        //set Listeners
        rectimage.setOnTouchListener(new MySecOnTouchListener());
        rectimage3.setOnTouchListener(new MyOnTouchListener());
        constraintLayout.setOnDragListener(new MyDragListener());
    }

    //OnTouchListener of the first Rect
    private final class MySecOnTouchListener implements View.OnTouchListener {
        public boolean onTouch(View sview, MotionEvent motionEvent){
            int action = motionEvent.getAction();
            if(action == MotionEvent.ACTION_DOWN);
                rectimage3.setVisibility(View.VISIBLE);
                constraintLayout.addView(rectimage3);

                ClipData data = ClipData.newPlainText("", "");
                View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(rectimage3);
                rectimage3.startDrag(data, shadowBuilder, rectimage3, 0);
                rectimage3.setVisibility(View.INVISIBLE);
                return true;
            } else{
                return false;
            }
        }
    }

    //OnTouchListener of the movable Rects
    private final class MyOnTouchListener implements View.OnTouchListener {
        public boolean onTouch(View view, MotionEvent motionEvent){
            int action = motionEvent.getAction();
            if (action == MotionEvent.ACTION_DOWN) {
                ClipData data = ClipData.newPlainText("", "");
                View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
                view.startDrag(data, shadowBuilder, view, 0);
                view.setVisibility(View.INVISIBLE);
                return true;
            } else {
                return false;
            }
        }
    }

    //OnDragListener of the Layout
    class MyDragListener implements View.OnDragListener{
        @Override
        public boolean onDrag(View v, DragEvent event) {
            View view = (View) event.getLocalState();

            switch (event.getAction()) {
                case DragEvent.ACTION_DRAG_STARTED:
                    view.setVisibility(View.VISIBLE);
                    break;
                case DragEvent.ACTION_DRAG_LOCATION:
                    view.setX(event.getX()-(view.getWidth()/2));
                    view.setY(event.getY()-(view.getHeight()/2));
                    break;
                case DragEvent.ACTION_DROP:
                    break;
            }
            return true;
        }
    }
}

Solution

  • You have to bind views and access methods only inside main method or after main method.

    public class MainActivity extends AppCompatActivity {
        public ConstraintLayout constraintLayout;
        LayoutInflater inflater ;
        public View rectimage3 ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
    
        constraintLayout = (ConstraintLayout) findViewById(R.id.constraint_layout0);
        inflater = getLayoutInflater();
        rectimage3 = inflater.inflate(R.layout.my_rectview, constraintLayout, false);
        final ImageView rectimage = (ImageView) findViewById(R.id.rectimage);
    
        //set Listeners
        rectimage.setOnTouchListener(new MySecOnTouchListener());
        rectimage3.setOnTouchListener(new MyOnTouchListener());
        constraintLayout.setOnDragListener(new MyDragListener());
    }
    
    //OnTouchListener of the first Rect
    private final class MySecOnTouchListener implements View.OnTouchListener {
        public boolean onTouch(View sview, MotionEvent motionEvent){
            int action = motionEvent.getAction();
            if(action == MotionEvent.ACTION_DOWN);
                rectimage3.setVisibility(View.VISIBLE);
                constraintLayout.addView(rectimage3);
    
                ClipData data = ClipData.newPlainText("", "");
                View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(rectimage3);
                rectimage3.startDrag(data, shadowBuilder, rectimage3, 0);
                rectimage3.setVisibility(View.INVISIBLE);
                return true;
            } else{
                return false;
            }
        }
    }
    
    //OnTouchListener of the movable Rects
    private final class MyOnTouchListener implements View.OnTouchListener {
        public boolean onTouch(View view, MotionEvent motionEvent){
            int action = motionEvent.getAction();
            if (action == MotionEvent.ACTION_DOWN) {
                ClipData data = ClipData.newPlainText("", "");
                View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
                view.startDrag(data, shadowBuilder, view, 0);
                view.setVisibility(View.INVISIBLE);
                return true;
            } else {
                return false;
            }
        }
    }
    
    //OnDragListener of the Layout
    class MyDragListener implements View.OnDragListener{
        @Override
        public boolean onDrag(View v, DragEvent event) {
            View view = (View) event.getLocalState();
    
            switch (event.getAction()) {
                case DragEvent.ACTION_DRAG_STARTED:
                    view.setVisibility(View.VISIBLE);
                    break;
                case DragEvent.ACTION_DRAG_LOCATION:
                    view.setX(event.getX()-(view.getWidth()/2));
                    view.setY(event.getY()-(view.getHeight()/2));
                    break;
                case DragEvent.ACTION_DROP:
                    break;
            }
            return true;
        }
    }
    

    }