InstantiationException on Orientation Change when DialogFragment is on the top - android

I have a DialogFragment defined as inner class in my Fragment class. On Orientation Change even the following exception is poped up:
Caused by: android.app.Fragment$InstantiationException: Unable to instantiate fragment my.package.fragments.ImportFragment$FailedImportDialog: make sure class name exists, is public, and has an empty constructor that is public
at android.app.Fragment.instantiate(Fragment.java:585)
at android.app.FragmentState.instantiate(Fragment.java:96)
at android.app.FragmentManagerImpl.restoreAllState(FragmentManager.java:1682)
at android.app.Activity.onCreate(Activity.java:861)
at my.package.activities.ImportActivity.onCreate(ImportActivity.java:8)
at android.app.Activity.performCreate(Activity.java:4465)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
... 12 more
Caused by: java.lang.InstantiationException: can't instantiate class my.package.fragments.ImportFragment$FailedImportDialog; no empty constructor
at java.lang.Class.newInstanceImpl(Native Method)
at java.lang.Class.newInstance(Class.java:1319)
at android.app.Fragment.instantiate(Fragment.java:574)
But I do have public constructor:
class FailedImportDialog extends DialogFragment {
private EditText edtPassword;
private Button button;
public FailedImportDialog() { // Here it is!
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.another_password_dialog, container, false);
edtPassword = (EditText) v.findViewById(R.id.another_password_dialog_et_password);
getDialog().setTitle(R.string.failed_to_decrypt);
Button button = (Button) v.findViewById(R.id.another_password_dialog_btn_ok);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
});
return v;
}
}
Here is xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="10dp">
<TextView android:id="#+id/another_password_dialog_tv_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/what_password_did_you_use">
</TextView>
<EditText android:id="#+id/another_password_dialog_et_password"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:inputType="textPassword">
<requestFocus>
</requestFocus>
</EditText>
<Button android:id="#+id/another_password_dialog_btn_ok"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:text="OK">
</Button>
</LinearLayout>
Do you guys know why this exception happens? Thank you!
UPDATE: If I move a class to a separate file there is no such an exception, everything goes smoothly. So the question is - why this exception happens when DialogFragment is an inner class?

Calling setRetainInstance(true) will cause the FragmentManager to save your actual Fragment instance. Instead of destroying and recreating the Fragment, it will just pass the same one along to the new Activity.

try making the inner class static:
public static class FailedImportDialog extends DialogFragment
I will post more explanation about this in a while. In the meantime, try this and let me know if it works.

Define your inner class like this:
public class FailedImportDialog extends DialogFragment {
....
}
With the public notation.
Because, this is what your LogCat says:
Caused by: android.app.Fragment$InstantiationException: Unable to instantiate fragment
my.package.fragments.ImportFragment$FailedImportDialog: make sure class name exists
is public, and has an empty constructor that is public

Related

Android: how do I setEnabled(true) on a CardView in onResume?

I have a RecyclerView list with CardViews. I added the following code below to launch an activity (ActActivity) that allows the user to edit the CardView. The setEnabled(false) code is used to keep multiple instances of the activity from opening if the user clicks multiple times in rapid succession on the CardView. I only want one instance of the activity to be open at one time so that the user is only editing the single CardView that they clicked on.
My problem is that when I add the onResume() section to re-set setEnabled() to "true" the app crashes. When I remove the onResume() section then the setEnabled(false) code works correctly by not allowing multiple instances of the activity to open, but the problem is that any doubleclicks on the CardView disable a future single-click to correctly launch the ActActivity.
What am I missing here?
MainActivity.java
public class MainActivity extends AppCompatActivity implements
RecyclerItemClickListener {
lvContact = (RecyclerView) findViewById(R.id.lvContact);
assert lvContact != null;
lvContact.setHasFixedSize(true);
contactListAdapter = new ContactListAdapter(this);
contactListAdapter.setOnItemClickListener(this);
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
lvContact.setLayoutManager(layoutManager);
lvContact.setAdapter(contactListAdapter);
...
#Override
public void onItemClick(int position, View view) {
CardView c = (CardView) view;
c.setEnabled(false);
ActActivity.start(this, contactListAdapter.getItem(position));
}
...
Override
protected void onResume() {
super.onResume();
CardView cardView1 = (CardView) findViewById(R.id.singlecard_view1);
cardView1.setEnabled(true);
}
xml file for the RecyclerView:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
tools:context="com.v050.MainActivity">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" >
</include>
<LinearLayout
android:id="#+id/todoListLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar"
android:layout_above="#+id/s4"
android:background="#color/background4main"
android:layout_marginTop="6dp"
android:layout_marginStart="6dp"
android:layout_marginLeft="6dp"
android:layout_marginEnd="6dp"
android:layout_marginRight="6dp"
android:layout_marginBottom="6dp"
android:orientation="vertical" >
<android.support.v7.widget.RecyclerView
android:id="#+id/lvContact"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
</LinearLayout>
<TextView
android:id="#+id/s4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:gravity="center"
android:textStyle="bold"
android:textColor="#FFFFFF"
android:background="#color/colorPrimary"
android:textAppearance="?android:attr/textAppearanceMedium"
android:paddingTop="15dp"
android:paddingBottom="15dp"
android:clickable="true" />
</RelativeLayout>
xml file for the CardView:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/singlecard_view1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
card_view:cardBackgroundColor="#android:color/white"
card_view:cardCornerRadius="6dp"
card_view:cardElevation="4dp"
android:foreground="?android:attr/selectableItemBackground"
android:longClickable="true" >
Logcat output does not like the "cardView1.setEnabled(true)" line in the onResume() section:
11-01 23:22:54.814 1399-1399/com.example.v50 E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to resume activity {com.example.v50/com.v050.MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2575)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2603)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2089)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.v050.MainActivity.onResume(MainActivity.java:279)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1184)
at android.app.Activity.performResume(Activity.java:5082)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2565)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2603) 
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2089) 
at android.app.ActivityThread.access$600(ActivityThread.java:130) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195) 
at android.os.Handler.dispatchMessage(Handler.java:99) 
at android.os.Looper.loop(Looper.java:137) 
at android.app.ActivityThread.main(ActivityThread.java:4745) 
at java.lang.reflect.Method.invokeNative(Native Method) 
at java.lang.reflect.Method.invoke(Method.java:511) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
at dalvik.system.NativeStart.main(Native Method) 
One proposed answer that works is:
...
#Override
public void onItemClick(int position, final View view) {
view.setEnabled(false);
ActActivity.start(this, contactListAdapter.getItem(position));
view.post(new Runnable() {
#Override
public void run() {
view.setEnabled(true);
}
});
}
How does this compare to answers that use onResume?
Here is problem .....
CardView is in the recycle view and you are trying from the main layout instead of item layout ....
here is your solution for your problem....
create cardview variable as global .......
private CardView cardview;
use it when the item clicked ......
#Override
public void onItemClick(int position, View view) {
cardview = (CardView) view;
cardview.setEnabled(false);
ActActivity.start(this, contactListAdapter.getItem(position));
}
Note:- Always try to declare global variable which have use in many methods .....
EDIT:- try this for the first run in your onResume....
and put condition onResume ....
Override
protected void onResume() {
super.onResume();
if(cardview!=null){
cardview.setEnabled(true);
}
above problem will solve your First Run problem ....
You can initialise the card view in onCreate of activity instead of onResume.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CardView cardView1 = (CardView)findViewById(R.id.singlecard_view1);
}
Override
protected void onResume() {
super.onResume();
cardView1.setEnabled(true);
}
Have you initialized the RecyclerView contact list before following code:
CardView cardView1 = (CardView)findViewById(R.id.singlecard_view1);
If you haven't then the card view will not be created and findViewById(R.id.singlecard_view1);
will return null.
Edited:
I think the view of the RecyclerView's items are not getting initialized untill activity is fully visible which cause findViewById(R.id.singlecard_view1) return null.
But as you have said you just want the edit activity to be started only once.
You can achieve this by-> adding android:launchMode="singleTask" for "ActActivity" in manifest file. OR
->adding FLAG_ACTIVITY_CLEAR_TASK to Intent.

Hide/Show Button in Fragment from Activity

i am trying to hide/show Button in fragment from Activity but it give me following exception.
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
Home Activity
public class HomeActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
CategoryFragment frag=(CategoryFragment) activity.getSupportFragmentManager()
.findFragmentByTag("cat_frag");
Button newDesigns= (Button) frag.getView().findViewById(R.id.new_designs);
newDesigns.setVisibility(View.VISIBLE);
}
}
Category Fragment
public class CategoryFragment extends Fragment{
Button newDesigns;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_category, null);
newDesigns= (Button) v.findViewById(R.id.new_designs);
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#CCCCCC">
<TextView
android:id="#+id/list_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:background="#drawable/shape_logo_bg"
android:gravity="center"
android:padding="5dp"
android:textColor="#android:color/white"
android:textSize="18sp" />
<Button
android:id="#+id/new_designs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/list_name"
android:background="#color/edit_button_color"
android:padding="10dp"
android:text="#string/new_designs"
android:textColor="#color/btn_text_color"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dp"
android:visibility="gone"
/>
</RelativeLayout>
Code is too large to be posted here. Thats why i have only posted the code where i am finding an issue.
I am able to get newDesigns BUTTON instance.What is shocking for me is if try to play with button instance (VISIBLE/GONE) it gives me above mentioned exception.
Help is appreciated.
You shouldn't play with a view of the Fragment while you are in a Activity directly. You will not know what the view's state will be and this can potentially lead to issues you can't even think of(beleive me i faced many). To interact with the activity's views, make an interface:
public interface AccessFragmentViews{
public void setVisibilityForButton(boolean bool);
//any other methods that you need
}
Now implement this inside the fragment class and override the method.
class YourFragment implements AccessFragmentViews{
.
.
public void serVisibilityForButton(boolean shouldHide){
if(shouldHide){
yourButton.setVisibility(View.GONE);
}else{
yourButton.setVisibility(View.VISIBLE);
}
}
}
Now you can interact safely with the views of the fragment within a activity using this interface. Make sure that the fragment is alive before doing so though ;) accessing child's view are prone to WindowLeakedExceptions and illegalstateexceptions
In the activity use it as follows:
you can get the fragment reference by either finding it by its tag or by using the reference you used to create the fragment
//NOTE: it is very very dangerous to do the accessing on a fragment views from an activity
//first the alive check then the logic
if(yourFragmentReference!=null){
((AccessFragmentViews)yourFragmentReference).setVisibilityForButton(true);// or false if you want to make it visible
}
Add a method in your fragment class
public void changeButtonVisibility(boolean visibility){
if(visibility){
newDesigns.setVisibility(View.VISIBLE);
}else{
newDesigns.setVisibilty(View.GONE);
}
}
and in your activity class
add this line
public class HomeActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
CategoryFragment frag=(CategoryFragment) activity.getSupportFragmentManager()
.findFragmentByTag("cat_frag");
frag.changeButtonVisibility(true);
}
}

Not able to set text of textview from other activity

i have main activity:
public class MainActivity extends AppCompatActivity {
Button btnadd;
int a1 = 10;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnadd = (Button) findViewById(R.id.btnadd);
btnadd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final SecondAct sa = new SecondAct();
sa.ttl(a1);
}
});
}
}
and i have other activity:
public class SecondAct extends Activity {
public TextView txt2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
txt2 = (TextView) findViewById(R.id.txt2);
}
public void numsum(int no)
{
txt2.setText(String.valueOf(no));
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:id="#+id/btnadd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="addd"></Button>
<LinearLayout
android:layout_below="#+id/btnadd"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/second"></include>
</LinearLayout>
</RelativeLayout>
When i click on button from main activity to set textview text of second activity then it gives me error.
Error:
FATAL EXCEPTION: main
Process: com.example.sumdemo, PID: 13809
java.lang.NullPointerException
at com.example.sumdemo.MainActivity$1.onClick(MainActivity.java:28)
at android.view.View.performClick(View.java:4463)
at android.view.View$PerformClick.run(View.java:18770)
at android.os.Handler.handleCallback(Handler.java:808)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5333)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:824)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:640)
at dalvik.system.NativeStart.main(Native Method)
How can i set second activity value from main activity without passing data through intent ?
final SecondAct sa = new SecondAct();
sa.ttl(a1);
never use the new operator on a class that extends Activity. You have to use startActivity to start SecondAct, and provide additional info through the Intent object
Use Application class with a static parameter.
That is
class MyApp extends Application{
public static TextView tv;
}
in the first activity:
usemyapp.tv = (TextView) findViewById(...);
in oreder to have an access from somewhere use this:
if (MyApp.tv != null)
MyApp.tv.setText("a new text");
do not forget to wrap it in mainUiThread by using a handler.
in AndroidMainfest.xml file use this:
<application
android:name=".MyApp" <<<<<<<<<<<<<<<<<<<<<<<this the name of the class
>
Futhermore, do not create an activity class by a constructor. this is a very very bad idea:) You have this error because you have created the class but onCreate() method has not called and has not attached to Android UI process.
Use this question as guide.
How to manage `startActivityForResult` on Android?
And don't try to change one activity content from another activity.
When you create an Activity object through its constructor, you can't call its life cycle methods (e.g onCreate) so your activity doesn't have a View and you can't access your views. you must use startActivity and let android handle creating Activity object and call its life cycle method. you should change its view after inflating view. for your case, you can pass extra data via Intents and use that data in your second Activity

error on setOnclickListener in my activity

((Button)findViewById(2131230768)).setOnClickListener(new MainMenuActivity(this));
View.OnClickListener runGameListener = new MainMenuActivity(this);
I have implemented onclicklistener even though it gives error on mainmenuactivity
my class is
public class MainMenuActivity
extends Activity implements OnClickListener
please help me..
Assume you have layout sample_activity.
Here's the code for sample_activity.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="GO!!"
android:id="#+id/buttonGo"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="170dp" />
</RelativeLayout>
And MainActivity.class :
public class MainActivity extends ActionBarActivity {
Button goButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sample_activity);
goButton = (Button) findViewById(R.id.buttonGo);
goButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//....Do all the stuffs here
}
});
}
First, never search for views by their generated id value. Use the identifier name instead, e.g.
findViewById(R.id.your_button)
Second, new with an Activity is not correct. Don't instantiate activities yourself.
Since your activity implements View.OnClickListener and assuming the code is in the same activity, just use
setOnClickListener(this)
That is,
findViewById(R.id.your_button).setOnClickListener(this);
(setOnClickListener() is a View method so casting to Button is not needed here.)
Firstly check your id of button from xml is write or not? I think your id is wrong its giving error..

Classcastexception: Widget cannot be cast to layout

Though this tends to be very basic question, i cannot solve this issue. I searched the similar kind of issue but none solves my issue.
I created my own class where i created some basic controls and i called this class in my xml as
<com.mypackagename.classname
..
..
/>
and some views goes inside this. and before this now i would like to add relativelayout as
activity_main1.xml:
<RelativeLayout xmlns:android="schemas.android.com/apk/res/android"
xmlns:android1="http://schemas.android.com/apk/res/android"
android1:layout_width="match_parent"
android1:layout_height="wrap_content" >
<com.test.MainLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainlayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/drawer_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:src="#drawable/ic_drawer" />
</LinearLayout>
</com.test.MainLayout>
</RelativeLayout >
and i my main activity i declared as
MainActivity:
Myview view;
view = (Myview)this.getLayoutInflater().inflate(R.layout.activity_main1, null);
setContentView(view);
where MyView is the class where i have my own controls.
After adding relative layout i tried something like
MainActivity1.java:
public class MainActivity1 extends FragmentActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
RelativeLayout item = (RelativeLayout)findViewById(R.id.item);
view = (Myview)this.getLayoutInflater().inflate(R.layout.activity_main1, null);
item.addView(view);
setContentView(item); // facing an error here
.......... rest of the code
}
and my layout activity is
public class MainLayout1 extends LinearLayout
{
....
}
while running it is throwing classcastexception and the error is
java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to com.view.layout.MainLayout
view = (Myview)this.getLayoutInflater().inflate(R.layout.activity_main1, null);
At this point in your java class, you are getting MyView Object in view, but it is actually a layout file instance which returns its parent layout here its a RelativeLayout.
Since inflate(R.layout.activity_main1, null); returns the object of RelativeLayout. Instead of this you have to get instance of your MainLayout1 like(R.id.mainlayout) and then cast it into the MyView object like:
RelativeLayout item = (View)this.getLayoutInflater().inflate(R.layout.activity_main1,null);
view = (Myview) item.findViewById(R.id.mainlayout);
item.addView(view);
setContentView(item);

Categories

Resources