Results 1 to 5 of 5
  1. #1
    Zarah is offline Senior Member
    Join Date
    Mar 2014
    Posts
    286
    Rep Power
    7

    Default ClassCastException in a third-party library after I tried to fiddle with 'my' code

    I am attaching an Eclipse project named ExpandableRecyclerView@GitHubTestTwo which is a previous error-free version, and ExpandableRecyclerView@GitHubTestThree which is after I messed iup.

    expandablerecyclerview.zip
    ExpandableRecyclerView@GithubTestThree.zip
    ExpandableRecyclerView@GithubTestTwo.zip

    __________________________________________________ _________________________________

    I need an Activity with an expandable RecyclerView like the one in this picture:

    ClassCastException in a third-party library after I tried to fiddle with 'my' code-fasnt.png

    So I am using this third party library project . That part works.

    The problem arose when I did what I am describing in the next two paragraphs:

    My next requirement is that I want different child-rows for different parent-rows. I am reproducing (if that's the right word) this example to create multiple child-viewholders.

    The idea is basically to have the different Child-viewholders (corresponding to each child-row style) extending one common childview-holder, and then inside our ExpandableRecyclerAdapter where we are passed the ArrayList of the data displayed in parent-rows in the constructor (`parentItemList` in the SSCCE), we declare constants representing all the child-row-types (TYPE_EDITTEXT and TYPE_SPINNER in the SSCCE below); and then inside `getItemViewType(int position)` we compare the data item from `parentItemList` using the passed `int position` as the index, with each text string on parent-rows and in each case, assign the `viewType` int variable a TYPE constant, and the `viewType`.Then this `int viewType` is passed to the `onCreateChildViewHolder` and `onBindChildViewHolder`, so we execute another switch-block in the definitions of each of these methods and then in onCreateChildViewHolder we return a corresponding ChildViewHolder (inflated from a corresponding layout resource) (either `R.layout.custom_row_child_with_edittext` or `R.layout.custom_row_child_with_spinner` in the SSCCE) ; and in `onBindChildViewHolder`, update the data according to the case in the switch-block.

    The problem is the dollowing ClassCastException:

    Java Code:
    07-26 18:21:54.380: E/AndroidRuntime(276): FATAL EXCEPTION: main
    07-26 18:21:54.380: E/AndroidRuntime(276): java.lang.ClassCastException: tests.test.epmc_mobile.search_module.no_ui.expandable_recycler_view.EPMCChildViewHolder
    07-26 18:21:54.380: E/AndroidRuntime(276):      at com.bignerdranch.expandablerecyclerview.Adapter.ExpandableRecyclerAdapter.onBindViewHolder(ExpandableRecyclerAdapter.java:144)
    The thing is that ExpandableRecyclerAdapter.java is a part of the third party library project, and Line#144 (and 142 and 143 which I added) are:

    Java Code:
    Log.i(TAG, "+++++++++++++++++++++++++THE TYPE OF THE RecyclerView.ViewHolder WHICH HAS BEEN PASSED AS AN ARGUMENT IS "
    					+ holder.getClass().getSimpleName() + "++++++++++++++++++++++++++++");
    			PVH parentViewHolder = (PVH) holder;
    and this logs

    Java Code:
    07-26 19:23:14.109: I/Class(277): +++++++++++++++++++++++++THE TYPE OF THE RecyclerView.ViewHolder WHICH HAS BEEN PASSED AS AN ARGUMENT IS MyChildViewHolder++++++++++++++++++++++++++++
    Before I tried to do what I am doing above, it was working fine.

    SSCCE CODE:

    MainActivity.java

    [CODE]
    Java Code:
    public class MainActivity extends FragmentActivity {
    	private static final String TAG = MainActivity.class.getSimpleName();
    	private RecyclerView recyclerView;
    	private static int [] imageIds = {R.drawable.ic_action_call, R.drawable.ic_action_copy, R.drawable.ic_action_discard};
    	private static String [] titles = {"Dummy Text One", "Dummy Text Two", "Dummy Text Three"};
    
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		Log.i(TAG, "onCreate of MainActivity called.");//check
    		super.onCreate(savedInstanceState);
    		
    		setContentView(R.layout.activity_main);
    		recyclerView = (RecyclerView) findViewById(R.id.mainActivity_recyclerView);
    		
    		MyExpandableRecyclerAdapter myExpandableRecyclerAdapter = new MyExpandableRecyclerAdapter(this, populateDataList(this));
    		recyclerView.setAdapter(myExpandableRecyclerAdapter);
    		recyclerView.setLayoutManager(new LinearLayoutManager(this)); 
    	}
    	
    	private ArrayList<ParentObject> populateDataList(Context context) {
    		Log.i(TAG, "populateDataList of MainActivity called.");//check
    		ArrayList<ParentObject> parentObjectList = new ArrayList<>();
    		for (int i=0; i<imageIds.length && i<titles.length; i++) {
    			MyCustomParentObject myCustomParentObject = new MyCustomParentObject(context);
    			myCustomParentObject.setImageId(imageIds[i]);
    			myCustomParentObject.setTitle(titles[i]);
    			parentObjectList.add(myCustomParentObject);
    		} 
    		return parentObjectList;
    	}
    }
    MyExpandableRecyclerAdapter.java

    Java Code:
    public class MyExpandableRecyclerAdapter extends ExpandableRecyclerAdapter<ParentViewHolder, ChildViewHolder> {
    	private static final String TAG = MyExpandableRecyclerAdapter.class.getSimpleName();
    	LayoutInflater layoutInflater;
    	Context context;
    	private List<ParentObject> parentItemList = new ArrayList<>();
    	
    	private static final int TYPE_EDITTEXT = 0;
    	private static final int TYPE_SPINNER = 1;
    
    	
    	public MyExpandableRecyclerAdapter(Context context, List<ParentObject> parentObjectItemsList) {
    		super(context, parentObjectItemsList);
    		Log.i(TAG, "Constructor of MyExpandableRecyclerAdapter called.");//check
    		layoutInflater = LayoutInflater.from(context);
    		this.context = context;
    		parentItemList = parentObjectItemsList;
    	}
    	
    	
    	
    	@Override
    	public int getItemViewType(int position) {
    		int viewType;
    		if (parentItemList.get(position).equals("EditText Entry")) {
    			viewType = TYPE_EDITTEXT;
    		} else {
    			viewType = TYPE_SPINNER;
    		}
    		return viewType; 
    	}
    	
    	
    	
    
    	@Override
    	public MyParentViewHolder onCreateParentViewHolder(ViewGroup container, int viewType) {
    		Log.i(TAG, "onCreateParentViewHolder of MyExpandableRecyclerAdapter called.");//check
    		Log.i(TAG, "IN onCreateParentViewHolder, THE TYPE OF AN ITEM IN THE parentItemList IS " + parentItemList.get(1));
    		return new MyParentViewHolder(layoutInflater.inflate(R.layout.custom_row_parent, container, false));
    	}
    
    	
    	
    	@Override
    	public MyChildViewHolder onCreateChildViewHolder(ViewGroup container, int viewType) {
    		Log.i(TAG, "onCreateChildViewHolder of MyExpandableRecyclerAdapter called.");//check
    		switch(viewType) {
    		case TYPE_EDITTEXT:
    			return new MyChildViewHolder(layoutInflater.inflate(R.layout.custom_row_child_with_edittext, container, false), context);
    		case TYPE_SPINNER:
    			return new MyChildViewHolder(layoutInflater.inflate(R.layout.custom_row_child_with_spinner, container, false), context);
    		default:
    			return new MyChildViewHolder(layoutInflater.inflate(R.layout.custom_row_child_with_edittext, container, false), context);
    		}
    	}
    
    	
    	
    	@Override
    	public void onBindParentViewHolder(ParentViewHolder parentViewHolder, int position, Object parentObject) {
    		Log.i(TAG, "onBindParentViewHolder of MyExpandableRecyclerAdapter called.");//check
    		MyParentViewHolder myParentViewHolder = (MyParentViewHolder) parentViewHolder;
    		MyCustomParentObject myCustomParentObject = (MyCustomParentObject) parentObject;
    		myParentViewHolder.textView.setText(myCustomParentObject.getTitle());
    		myParentViewHolder.imageView.setImageResource(myCustomParentObject.getImageId()); 
    	}
    	
    	
    
    	@Override
    	public void onBindChildViewHolder(ChildViewHolder childViewHolder, int position, Object childObject) {
    		Log.i(TAG, "onBindChildViewHolder of MyExpandableRecyclerAdapter called.");//check
    		
    		switch(childViewHolder.getItemViewType()) {
    		case TYPE_EDITTEXT:
    			MyChildViewHolderWithEditText myChildViewHolderWithEditText = (MyChildViewHolderWithEditText) childViewHolder;
    			myChildViewHolderWithEditText.textView.setText("TextView " + (position+1) + " Title"); 
    		case TYPE_SPINNER:
    			MyCustomChildObject myCustomChildObject = (MyCustomChildObject) childObject;
    			ArrayAdapter arrayAdapter = new ArrayAdapter(context, android.R.layout.simple_list_item_1, myCustomChildObject.getSpinnerItems());
    			arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    			MyChildViewHolderWithSpinner myChildViewHolderWithSpinner = (MyChildViewHolderWithSpinner) childViewHolder;
    			myChildViewHolderWithSpinner.spinner.setAdapter(arrayAdapter);
    		}
    	}
    	
    }
    MyCustomParentObject.java

    Java Code:
    public class MyCustomParentObject implements ParentObject {
    	private static final String TAG = MyCustomParentObject.class.getSimpleName();
    	//List to store all the children of the parent object in.
        private List<Object> childObjectList;
        private String [] bib;
        
        MyCustomParentObject (Context context) {
        	super();
        	bib = context.getResources().getStringArray(R.array.spinner_options);
        }
    	
    
    	@Override
    	public List<Object> getChildObjectList() {
    		Log.i(TAG, "getChildObjectList of MyCustomParentObject called.");//check
            //"You can either return a newly created list of children here or attach them later"
    		return populateChildObjectList();
    	}
    	
    	@Override
    	public void setChildObjectList(List<Object> childObjectList) {
    		Log.i(TAG, "setChildObjectList of MyCustomParentObject called.");//check
    		childObjectList = childObjectList;
    	}
    	
    	private List<Object> populateChildObjectList() {
    		Log.i(TAG, "populateChildObjectList of MyCustomParentObject called.");//check
    		childObjectList = new ArrayList<>();
    		MyCustomChildObject myCustomChildObject = new MyCustomChildObject();
    		myCustomChildObject.setSpinnerItems(bib);
    		Object myCustomChildObjectCasted = (Object) myCustomChildObject;
    		childObjectList.add(myCustomChildObjectCasted);
    		return childObjectList;
    	}
    
    	
    	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    	private int imageId;
    	private String title;
    	public int getImageId() {
    		Log.i(TAG, "getImageId of MyCustomParentObject called.");//check
    		return imageId;
    	}
    	public void setImageId(int imageId) {
    		Log.i(TAG, "setImageId of MyCustomParentObject called.");//check
    		this.imageId = imageId;
    	}
    	public String getTitle() {
    		Log.i(TAG, "getTitle of MyCustomParentObject called.");//check
    		return title;
    	}
    	public void setTitle(String title) {
    		Log.i(TAG, "setTitle of MyCustomParentObject called.");//check
    		this.title = title;
    	}
    
    }
    MyCustomChildObject.java

    Java Code:
    public class MyCustomChildObject {
    	private static final String TAG = MyCustomParentObject.class.getSimpleName();
    
    	private String [] spinnerItems;
    
    	public String [] getSpinnerItems() {
    		return spinnerItems;
    	}
    
    	public void setSpinnerItems(String [] spinnerItems) {
    		this.spinnerItems = spinnerItems;
    	}
    
    }
    MyParentViewHolder.java

    Java Code:
    public class MyParentViewHolder extends ParentViewHolder {
    	private static final String TAG = MyParentViewHolder.class.getSimpleName();
    	TextView textView;
    	ImageView imageView;
    
    	public MyParentViewHolder(View itemView) {
    		super(itemView);
    		Log.i(TAG, "Constructor of MyParentViewHolder called.");//check
    		textView = (TextView) itemView.findViewById(R.id.parentCustomRow_textView);
    		imageView = (ImageView) itemView.findViewById(R.id.parentCustomRow_imageView);
    	}
    
    }

    MyChildViewHolder.java

    Java Code:
    public class MyChildViewHolder extends ChildViewHolder {
    	private static final String TAG = MyChildViewHolder.class.getSimpleName();
    
    	public MyChildViewHolder(View itemView, final Context context) {
    		super(itemView);
    		Log.i(TAG, "Constructor of MyChildViewHolder called.");// check
    	}
    }
    MyChildViewHolderWithEditText.java

    Java Code:
    public class MyChildViewHolderWithEditText extends MyChildViewHolder {
    	EditText editText;
    	TextView textView;
    
    	public MyChildViewHolderWithEditText(View itemView, Context context) {
    		super(itemView, context);
    		
    		textView = (TextView) itemView.findViewById(R.id.childViewHolderWithEditText_TextView);
    		editText = (EditText) itemView.findViewById(R.id.childViewHolderWithEditText_editText);
    	}
    
    }
    MyChildViewHolderWithSpinner.java

    Java Code:
    public class MyChildViewHolderWithSpinner extends MyChildViewHolder {
    	Spinner spinner;
    
    	public MyChildViewHolderWithSpinner(View itemView, Context context) {
    		super(itemView, context);
    
    		spinner = (Spinner) itemView.findViewById(R.id.childViewHolderWithSpinner_spinner);
    		//ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(context, R.array.childViewSpinnerFields, android.R.layout.simple_spinner_item);
    		//adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    		///spinner.setAdapter(adapter);
    		spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
    			@Override
    			public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {}
    			@Override
    			public void onNothingSelected(AdapterView<?> parent) {}
    		});
    	}
    
    }
    Last edited by Zarah; 07-26-2015 at 05:06 PM.

  2. #2
    Zarah is offline Senior Member
    Join Date
    Mar 2014
    Posts
    286
    Rep Power
    7

    Default Re: ClassCastException in a third-party library after I tried to fiddle with 'my' cod

    By comparing Line#13 of this stack-trace of the error free program, and this one of the program which results in the exception, and by looking at the `onCreateViewHolder(ViewGroup viewGroup, int viewType)` method definition on Line#117 of this ExpandableRecyclerAdapter.java class, from which I infer that `onCreateViewHolder` is being passed the wrong viewType parameter.

    But I haven't yet been able to figure out why!

    __________________________________________________ __________________________________________________ ___________

    I think I have figured it out.

    Actually the trick of TYPE_SOMETHING constants that I am using in MyExpandableRecyclerAdapter is the same one they have used in ExpandableRecyclerAdapter, i.e. in my MyExpandableRecyclerAdapter, "0" is the value of TYPE_EDITTEXT and "1" is the value of TYPE_SPINNER; whereas in their ExpandableRecyclerAdapter, which is extended by my MyExpandableRecyclerAdapter, "0" is the value of TYPE_PARENT and "1" is the value of TYPE_CHILD.

    If the Android framework passes the same viewType parameter to onCreateViewHolder which is returned from getItemViewType(int position), it will pass 1 if it was TYPE_SPINNER in my MyExpandableRecyclerAdapter, but their ExpandableRecyclerAdapter will understand it as TYPE_CHILD, and thus call onCreateChildViewHolder.

    So I think the whole thing I am trying to achieve can't be done. =(
    Last edited by Zarah; 07-26-2015 at 07:15 PM.

  3. #3
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    Eastern Florida
    Posts
    20,003
    Rep Power
    33

    Default Re: ClassCastException in a third-party library after I tried to fiddle with 'my' cod

    So the problem looks like a poor design for the use of int values assigned to final variables. There are too many variables with the same int value, in this case 1.
    There are 4 billion different int values. There should be no excuse for using the same value for different variables.
    If you don't understand my response, don't ignore it, ask a question.

  4. #4
    Zarah is offline Senior Member
    Join Date
    Mar 2014
    Posts
    286
    Rep Power
    7

    Default Re: ClassCastException in a third-party library after I tried to fiddle with 'my' cod

    So the problem looks like a poor design for the use of int values assigned to final variables. There are too many variables with the same int value, in this case 1.
    There are 4 billion different int values. There should be no excuse for using the same value for different variables.
    The Android framework calls onCreateViewHolder(ViewGroup viewGroup, int viewType) and it is originally an abstract method of RecyclerView.Adapter in Android framework. Normally we override it in our RecyclerView.Adapter implementations and return from it an instance of a ViewHolder (which I normally inflate from XML).

    Now its definition in ExpandableRecyclerAdapter is

    Java Code:
    @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
            if (viewType == TYPE_PARENT) {
                PVH pvh = onCreateParentViewHolder(viewGroup);
                pvh.setParentItemClickListener(this);
                return pvh;
            } else if (viewType == TYPE_CHILD) {
                return onCreateChildViewHolder(viewGroup);
            } else {
                throw new IllegalStateException("Incorrect ViewType found");
            }
        }
    You can see that it is doing nothing but calling an appropriapte abstract method based on the viewType called, and then those methods (onCreateParentViewHolder and onCreateChildViewHolder) are what we override in our Adapter implementation to return appropriate ViewHolders. So onCreateViewHolder needs a viewType value of either 0 or 1.

    Suppose I gave TYPE_EDITTEXT a value of 3 and TYPE_SPINNER a value of 4, and return one of those from getItemViewCount(). The system would pass either 3 or 4 to onCreateViewHolder, and the above implementation would not be able to call onCreateParentViewHolder and onCreateChildViewHolder, and the app reaches a dead end.

    Do you still think there is a way to get what I need?
    Last edited by Zarah; 07-27-2015 at 11:02 AM.

  5. #5
    Xen
    Xen is offline Member
    Join Date
    Jan 2015
    Posts
    86
    Rep Power
    0

    Default Re: ClassCastException in a third-party library after I tried to fiddle with 'my' cod

    So you are using a parameter mechanism that is alreadby being used (for something else) and there is no way to pass your variable in a way that it doesn't coincide (or interfere, collide) with what is already happening, and this is creating your problem because the wrong method is called and it causes some misconceptions about what data is available, hence the miscast? And you are positive about it?

    I must say I am falling slightly in love with you. At least with the way you present your code and how you do the writeup, excellent! I think it is the type of proper writing and formatting that this forum likes to see, at least I do. I haven't read your code still.

    "I/Class(277)"

    ^ that is not very informative, is it? The I represents what, Integer? Pardon my ignorance.

    It's interesting what you do. Your code is nice. I feel I am with a like mind. Very refreshing, I must say.

    Quote Originally Posted by Norm View Post
    So the problem looks like a poor design for the use of int values assigned to final variables. There are too many variables with the same int value, in this case 1.
    There are 4 billion different int values. There should be no excuse for using the same value for different variables.
    It looks more like he is using a variable passing mechanism (parameter passing mechanism) that is predefined and already used? And he's trying to hitch onto it but it can't be done? That is at least the gist of the message.
    Last edited by Xen; 07-27-2015 at 10:02 AM.

Similar Threads

  1. Integrating 3rd party library JAVAZOOM
    By DONALD in forum Java Applets
    Replies: 0
    Last Post: 01-05-2012, 05:26 AM
  2. Code generation library?
    By kjkrum in forum Advanced Java
    Replies: 3
    Last Post: 05-25-2011, 01:48 AM
  3. Birthday Party Code
    By tonyfingures in forum New To Java
    Replies: 10
    Last Post: 09-16-2010, 03:24 AM
  4. Running a third-party-library based application in j2me
    By nishantsuneja in forum CDC and Personal Profile
    Replies: 0
    Last Post: 02-08-2009, 09:39 PM
  5. Need to hook up my jsp code to third party vendor
    By priya123 in forum JavaServer Pages (JSP) and JSTL
    Replies: 0
    Last Post: 08-28-2008, 10:24 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •