Search code examples
javaandroidarraylistandroid-custom-view

Passing ArrayList from MainActivity class to CustomView class in Android


We're trying to pass an ArrayList from Main Activity to use it in CustomView class.Both classes belong to the same activity.Depending on this array, some rectangles will be drawn on an image, but the array passed is always empty. We're newbies in Android and we've checked similar questions but nothing worked out with us.

This is the MainActivity.java class

package com.example.android.a3ozaarken;

import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {


    //private CustomView mcustomView;
    public static ArrayList<String[]> park_data = new ArrayList<String[]>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    private ProgressDialog pDialog;
    String JSON_STRING ;
    JSONArray jsonArray;
    JSONObject jsonObject;
    private CustomView customView;

    // public Hashtable<Integer, Integer> hash_data = new Hashtable<Integer, Integer>();
    // Hashtable <Integer, String> hashPlaces = new Hashtable<Integer,String>();


    public void getJSON(View view)
    {

        new BackgroundTask().execute();

    }


    class BackgroundTask extends AsyncTask<Void,Void,String>

    {    String json_url ;
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            json_url="http://192.168.1.103/erknly.php?id=0";

            pDialog = new ProgressDialog(MainActivity.this);
            pDialog.setMessage("Please wait...");
            pDialog.setCancelable(false);
            pDialog.show();

        }

        @Override
        protected String doInBackground(Void... voids) {
            try {
                URL url = new URL(json_url);
                HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                InputStream inputStream = httpURLConnection.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                StringBuilder stringBuilder = new StringBuilder();
                while((JSON_STRING = bufferedReader.readLine())!=null){
                    stringBuilder.append(JSON_STRING+"\n");
                }
                bufferedReader.close();
                inputStream.close();
                httpURLConnection.disconnect();
                return stringBuilder.toString().trim();

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Void... values) {
            super.onProgressUpdate(values);
        }

        @Override
        protected void onPostExecute(String result) {
            //super.onPostExecute(aVoid);
            TextView textView = (TextView) findViewById(R.id.textView);
            int count = 0 ;
            String places,status,id;

            if (pDialog.isShowing())
                pDialog.dismiss();
            try {
                jsonObject = new JSONObject(result);
                jsonArray = jsonObject.getJSONArray("ParkInfo");

                while(count < 5){

                    JSONObject jo = jsonArray.getJSONObject(count);
                    places = jo.getString("Places");
                    status = jo.getString("Status");
                    id = jo.getString("id");
                    // ParkInfo parkInfo = new ParkInfo(places,status,id);

                    park_data.add(new String[] { id,status});

                    count ++;

                }
                customView.postInvalidate();

            } catch (JSONException e) {
                e.printStackTrace();
            }

          //  textView.setText(park_data.get(1)[0]);

        }
    }
}

and this is the CustomView class

package com.example.android.a3ozaarken;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import com.example.android.a3ozaarken.MainActivity;
import com.example.android.a3ozaarken.R;

import java.util.ArrayList;

//import com.example.android.a3ozaarken.MainActivity;
//import com.example.android.a3ozaarken.ParkInfo;


public class CustomView extends View {

    private Paint red_paint,green_paint;
    private Rect rec_frame_red ;
    private Rect rec_frame_green;
    ArrayList<String[]> park_data;


    public CustomView(Context context) {
        super(context);

        init(null);
    }

    public CustomView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(attrs);
    }

    private void init (@Nullable AttributeSet set){
        setBackgroundResource(R.drawable.lot2);
        red_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        green_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        rec_frame_green = new Rect();
        rec_frame_red = new Rect();
        park_data = MainActivity.park_data;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        red_paint.setColor(Color.RED);
        red_paint.setStyle(Paint.Style.FILL);

        // rec_frame_red.set(370,225,490,575);
        //canvas.drawRect(rec_frame_red,red_paint);


        green_paint.setColor(Color.GREEN);
        green_paint.setStyle(Paint.Style.FILL);

        // rec_frame_green.set(500,225,610,575);

        //  for (int i=0; i<mainActivity.park_data.size(); i++){
       // if(mainActivity.park_data.get(1).equals(1)){

            if(park_data.get(0)[0].equals(0)){

                rec_frame_green.set(370,225,490,575);
                canvas.drawRect(rec_frame_green,green_paint);
            }

//        }

        //    }

    }
}

and this is the error:

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.example.android.a3ozaarken, PID: 16157
                  java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
                      at java.util.ArrayList.get(ArrayList.java:411)
                      at com.example.android.a3ozaarken.CustomView.onDraw(CustomView.java:84)
                      at android.view.View.draw(View.java:17185)
                      at android.view.View.updateDisplayListIfDirty(View.java:16167)
                      at android.view.View.draw(View.java:16951)
                      at android.view.ViewGroup.drawChild(ViewGroup.java:3727)
                      at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3513)
                      at android.view.View.updateDisplayListIfDirty(View.java:16162)
                      at android.view.View.draw(View.java:16951)
                      at android.view.ViewGroup.drawChild(ViewGroup.java:3727)
                      at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3513)
                      at android.view.View.updateDisplayListIfDirty(View.java:16162)
                      at android.view.View.draw(View.java:16951)
                      at android.view.ViewGroup.drawChild(ViewGroup.java:3727)
                      at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3513)
                      at android.view.View.updateDisplayListIfDirty(View.java:16162)
                      at android.view.View.draw(View.java:16951)
                      at android.view.ViewGroup.drawChild(ViewGroup.java:3727)
                      at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3513)
                      at android.view.View.updateDisplayListIfDirty(View.java:16162)
                      at android.view.View.draw(View.java:16951)
                      at android.view.ViewGroup.drawChild(ViewGroup.java:3727)
                      at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3513)
                      at android.view.View.updateDisplayListIfDirty(View.java:16162)
                      at android.view.View.draw(View.java:16951)
                      at android.view.ViewGroup.drawChild(ViewGroup.java:3727)
                      at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3513)
                      at android.view.View.draw(View.java:17188)
                      at com.android.internal.policy.DecorView.draw(DecorView.java:753)
                      at android.view.View.updateDisplayListIfDirty(View.java:16167)
                      at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:648)
                      at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:654)
                      at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:762)
                      at android.view.ViewRootImpl.draw(ViewRootImpl.java:2800)
                      at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2608)
                      at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2215)
                      at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1254)
                      at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6337)
                      at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
                      at android.view.Choreographer.doCallbacks(Choreographer.java:686)
                      at android.view.Choreographer.doFrame(Choreographer.java:621)
                      at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
                      at android.os.Handler.handleCallback(Handler.java:751)
                      at android.os.Handler.dispatchMessage(Handler.java:95)
                      at android.os.Looper.loop(Looper.java:154)
                      at android.app.ActivityThread.main(ActivityThread.java:6119)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Application terminated.

Solution

  • You should not assign data at the time of view creation because you do not have any data at that time. So just let the view inflate, call a method of view to set value. Modify your class as following.

    public class CustomView extends View {
        private Paint red_paint,green_paint;
        private Rect rec_frame_red ;
        private Rect rec_frame_green;
        ArrayList<String[]> park_data;
        public CustomView(Context context) {
            super(context);
            init(null);
        }
    
        public CustomView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            init(attrs);
        }
    
        public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(attrs);
        }
    
        public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
            init(attrs);
        }
    
        private void init (@Nullable AttributeSet set){
            setBackgroundResource(R.drawable.lot2);
            red_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            green_paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            rec_frame_green = new Rect();
            rec_frame_red = new Rect();
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            red_paint.setColor(Color.RED);
            red_paint.setStyle(Paint.Style.FILL);
            green_paint.setColor(Color.GREEN);
            green_paint.setStyle(Paint.Style.FILL);
            if(park_data!=null && park_data.size()>0)
            if(park_data.get(0)[0].equals(0)){
                rec_frame_green.set(370,225,490,575);
                canvas.drawRect(rec_frame_green,green_paint);
            }
    
        }
    
        public void setValue(ArrayList<String[]> park_data){
            this.park_data=park_data;
            invalidate();
        }
    }
    

    On data load finish call setValue().

    customView.setValue(park_data)