Dialog fire non-static methods in main activity - java

I have a dialog that adds items to a listview, and when an item is added I need to reset the list adapter (because if not things get weird).
I read here that I can create an event listener and listen to it in the main activity. I tried doing so but it gives me errors.
AddMovieDialog.java:
public class AddMovieDialog extends DialogFragment {
private OnFinishListener onFinishListener;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
builder.setView(inflater.inflate(R.layout.add_movie_dialog, null))
.setTitle("Add a movie")
.setPositiveButton("Add", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// stuff
if (!movieName.isEmpty()) {
// stuff
if (AddMovieDialog.this.onFinishListener != null)
AddMovieDialog.this.onFinisheListener.finish();
}
}
});
// Create the AlertDialog object and return it
return builder.create();
}
public void setOnFinishListener(OnFinishListener listener) {
this.onFinishListener = listener;
}
public interface OnFinishListener {
void finish();
}
}
In the MainActivity:
AddMovieDialog addMovieDialog = new AddMovieDialog();
addMovieDialog.setOnFinishListener(new OnFinishListener() {
public void finish() {
}
});
But it gives me a compilation error: "The method setOnFinishListener(new OnFinishListener(){}) is undefined for the type AddMovieDialog"

You need to call a method which is non-static using the object. You can't call it using just the class name.
Change to this
AddMovieDialog addMovieDialog = new AddMovieDialog();
addMovieDialog .setOnFinishListener(new OnFinishListener() {
public void finish() {
}
});
Also shouldn't
if (AddMovieDialog.this.onCloseListener != null)
AddMovieDialog.this.onCloseListener.finish();
be
if (AddMovieDialog.this.onFinishListener != null)
AddMovieDialog.this.onFinishListener.finish();
EDIT
Seem your import statement in MainActivity is wrong. It should be something like com.yourpackagename.AddMovieDialog.OnFinishListener

Related

Android Java: AlertDialog method called from another class causes null pointer exception

I'm trying to call a method from another class which then calls an AlertDialog method, and I've tried many things but it always causes a null pointer exception. The calling class is running a web server, and I have a RecyclerView list on the activity class containing the method being called. here's some code from the activity class with AlertDialog:
public class ListClass extends AppCompatActivity {
private WebSvr server;
private static final int PORT = 8080;
private androidx.appcompat.widget.Toolbar toolbar;
private ListView lv;
private CustomAdapter customAdapter;
public ArrayList<EditModel> editModelArrayList;
public static String[] newList = new String[20];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_server_screen);
toolbar = (androidx.appcompat.widget.Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
startWebServer();
customAdapter = new CustomAdapter(this, editModelArrayList);
lv.setAdapter(customAdapter);
}
public static boolean listUpdated;
public void updateList() {
listUpdated = false;
Runnable r = new Runnable() {
#Override
public void run() {
for (int i = 0; i < 20; i++) {
if (CustomAdapter.editModelArrayList.get(i).getEditTextValue() != "") {
newList[i] = CustomAdapter.editModelArrayList.get(i).getEditTextValue();
} else {
if (!showNotification) {
runOnUiThread(new Runnable() {
#Override
public void run() {
showNullFieldNotification(); // <------------- CALLING THIS
}
});
showNotification = true;
}
}
}
listUpdated = true;
}
};
Thread thread = new Thread(r);
thread.start();
}
boolean showNotification = false;
public void showNullFieldNotification() {
new AlertDialog.Builder(ListClass.this)
.setTitle("Warning, some fields are empty")
.setNegativeButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.cancel();
showNotification = false;
}
}).show();
}
public static boolean returnListUpdated() {
return listUpdated;
}
...
}
And here's the code from my web server class:
public class WebSvr extends NanoHTTPD {
public ListClass ListClass = new ListClass();
public WebSvr(int port){
super(port);
}
#Override
public Response serve(String uri, Method method,
Map<String, String> header,
Map<String, String> parameters,
Map<String, String> files) {
ListClass.updateList(); // <--------------- THE METHOD CALLED
while (!ListClass.returnListUpdated()) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String strResponse = Arrays.toString(ListClass.returnString());
return newFixedLengthResponse(strResponse);
}
}
It always causes null pointer exception on this line:
new AlertDialog.Builder(ListClass.this)
and where the method is called in ListClass:
showNullFieldNotification();
Error message:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.espressif.iot_esptouch_demo, PID: 18217
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:152)
at android.view.ContextThemeWrapper.getTheme(ContextThemeWrapper.java:157)
at android.app.AlertDialog.resolveDialogTheme(AlertDialog.java:224)
at android.app.AlertDialog$Builder.<init>(AlertDialog.java:454)
at com.myProject.ListClass.showNullFieldNotification(ListClass.java:177)
at com.myProject.ListClass$4.run(ListClass.java:193)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6665)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:772)
If I call showNullFieldNotification() in ListClass onCreate() or from the options menu it works no problem, but when called from the WebSvr class it always causes the exception.
For context on the AlertDialog I've tried ListClass.this, getApplicationContext(), getBaseContext()... I've tried to save a context in onCreate as getApplicationContext() and use that.
I've tried to use the solution from this question to get context but that didn't work either. Would really appreciate any help.
EDIT: Forgot to mention that I had also tried to build the alert in this way:
public void showNullFieldNotification2() {
AlertDialog.Builder alert = new AlertDialog.Builder(ListClass.this);
alert.setTitle("Warning, some fields detected as being empty or having \"0\" as value");
alert.setNegativeButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.cancel();
showNotification = false;
}
});
AlertDialog dialog = alert.create();
dialog.show();
}
you forgot create Alert Dialog so it null, not the context
Android simple alert dialog
Got the solution from here in answer from Dan Bray. Needed to use a static context.
Since you are calling from outside of an activity, you'll need to save the context in activity class:
public static Context context;
And inside onCreate:
context = this;
To show notification:
new Handler(Looper.getMainLooper()).post(new Runnable(){
#Override
public void run(){
new AlertDialog.Builder(context)
.setTitle("Warning, some fields are empty")
.setNegativeButton("OK",new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialogInterface,int i){
dialogInterface.cancel();
showNotification=false;
}
}).show();
}
});
The methods called in the activity class must also be public static.

Saving Data from an android dialog

I am attempting to save data from an edit text field within a dialog to an ArrayList. I followed the methods of an answer to a similar question (found here How to store edit text data from an Android dialog?) however my code isn't exactly saving data. From my understanding I should be able to do the following(note it isnt the entire class, only the method in question):
public class StartNewGameActivity extends AppCompatActivity {
private ListView lv;
ArrayList<String> game_players = new ArrayList<String>();
public void addPlayerToGame(View view) {
DialogFragment newFragment = new CreatePlayerDialogFragment(
new CreatePlayerDialogFragment.MyMessageDialogListener(){
#Override
public void onClosed(String name) {
game_players.add(name);
}
});
newFragment.show(getSupportFragmentManager(), "players");
}
While using the following class:
public class CreatePlayerDialogFragment extends DialogFragment {
public interface MyMessageDialogListener {
public void onClosed(String name);
}
public AlertDialog onCreateDialog(final MyMessageDialogListener listener) {
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
final EditText input = new EditText(getActivity());
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
input.setLayoutParams(lp);
builder.setView(input);
builder.setMessage(R.string.player_name_dialog)
.setPositiveButton(R.string.player_name_dialog_add, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Add Player
{
if(listener != null) {
listener.onClosed(input.getText().toString());
}
dialog.cancel();
}
}
})
.setNegativeButton(R.string.player_name_dialog_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
// Create the AlertDialog object and return it
return builder.create();
}
}
However with my code I get an error "CreatePlayerDialogFrament() in CreatePlayerDialogFragment cannot be applied to CreatePlayerDialogFrament.MyMessageDialogListener"
Is it possibly because I am trying to do everything in my OnCreate() method? Im not quite sure what the issue is or how to go about solving it.

Android Splash Screen AsyncTask

Basically I have a loading splash screen which will be executed when button was clicked:
public void onClick(View v) {
// Load the loading splash screen
Intent loadingIntent = new Intent(context, LoadingScreen.class);
context.startActivity(loadingIntent);
}
});
And in the LoadingScreen class:
public class LoadingScreen extends Activity{
//A ProgressDialog object
private ProgressDialog progressDialog;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//Initialize a LoadViewTask object and call the execute() method
new LoadViewTask().execute();
}
//To use the AsyncTask, it must be subclassed
private class LoadViewTask extends AsyncTask<Void, Integer, Void>
{
//Before running code in separate thread
#Override
protected void onPreExecute()
{
progressDialog = ProgressDialog.show(LoadingScreen.this,"Getting routes...",
"Loading data, please wait...", false, false);
}
//The code to be executed in a background thread.
#Override
protected Void doInBackground(Void... params)
{
try
{
//Get the current thread's token
synchronized (this)
{
//Initialize an integer (that will act as a counter) to zero
int counter = 0;
//While the counter is smaller than four
while(counter <= 4)
{
//Wait 850 milliseconds
this.wait(750);
//Increment the counter
counter++;
//Set the current progress.
//This value is going to be passed to the onProgressUpdate() method.
publishProgress(counter*25);
}
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return null;
}
//Update the progress
#Override
protected void onProgressUpdate(Integer... values)
{
//set the current progress of the progress dialog
progressDialog.setProgress(values[0]);
}
//after executing the code in the thread
#Override
protected void onPostExecute(Void result)
{
finish();
//close the progress dialog
progressDialog.dismiss();
}
}
}
With these codes, the loading splash screen did came out. But I wonder is there any other way to show only the pop out dialogue for loading progress bar which on top on my previous screen?
Let's say my previous screen was event details. Then when user selected the button, only the dialogue box with loading progress bar will be shown instead of a new intent with a dialogue box.
Any ideas? Thanks in advance.
EDIT
public void onClick(View v) {
// Load the loading splash screen
new LoadViewTask().execute();
ENeighbourhoodActivity.tvDirection.setText("");
eventModel.setEventX(String.valueOf(eventModel.getEventX()));
eventModel.setEventY(String.valueOf(eventModel.getEventY()));
new GetEventDirectionAsyncTask(new GetEventDirectionAsyncTask.OnRoutineFinished() {
public void onFinish() {
//Hide the callout and plot user location marker
ENeighbourhoodActivity.callout.hide();
EventController.getUserLocation(context);
getActivity().finish();
}
}).execute(eventModel);
}
});
public class GetRegisteredEventAsyncTask extends
AsyncTask<String, Integer, Double> {
static EventController eventCtrl = new EventController();
public static ArrayList<Event> upcomingModel = new ArrayList<Event>();
public static ArrayList<Event> pastModel = new ArrayList<Event>();
public interface OnRoutineFinished { // interface
void onFinish();
}
private OnRoutineFinished mCallbacks;
public GetRegisteredEventAsyncTask(OnRoutineFinished callback) {
mCallbacks = callback;
}
public GetRegisteredEventAsyncTask() {
} // empty constructor to maintain compatibility
#Override
protected Double doInBackground(String... params) {
try {
upcomingModel = eventCtrl.getRegisteredUpcomingEvent(params[0]);
pastModel = eventCtrl.getRegisteredPastEvent(params[0]);
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Double result) {
if (mCallbacks != null)
mCallbacks.onFinish(); // call interface on finish
}
protected void onProgressUpdate(Integer... progress) {
}
}
In your onClick() method you could write something like:
new LoadViewTask().execute();
and the progress dialog will be shown in that page itself.
what are you doing man, just call your AsyncTask not the intent
public void onClick(View v)
{
new LoadViewTask().execute();
}
});
do your intent in postExecute
#Override
protected void onPostExecute(Void result)
{
finish();
//close the progress dialog
progressDialog.dismiss();
//START YOUR ACTIVITY HERE
Intent loadingIntent = new Intent(context, LoadingScreen.class);
context.startActivity(loadingIntent);
}
Must read the documentation of AsynTask

To execute AsyncTask from onClick(DialogInterface dialog)

Currently I have two java class, 1 with AsyncTask and another one is with extend DialogFragment.
I would like to call CreateGroupTask(AsyncTask) in ChooseAddContact java class.
I have tried several recommended ways to execute the AsyncTask java but all failed.
Any recommendation or solution to that?
public class ChooseAddContact extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.pick_add)
.setItems(R.array.contact_array, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (which == 0){
AddContactDialog dialog2 = new AddContactDialog();
dialog2.show(getFragmentManager(), "AddContactDialog");
} else if (which == 1){
**How should I CALL it here??
//new CreateGroupTask().execute();
//makegroup = new CreateGroupTask();
//makegroup.execute();
}**
}
});
return builder.create(); }
}
And
public class CreateGroupTask extends AsyncTask<Void, Void, String> {
private Context mContext;
private ProgressDialog pd;
public CreateGroupTask() {
}
public CreateGroupTask(Context mContext) {
super();
this.mContext = mContext;
}
#Override
protected void onPreExecute() {
pd = ProgressDialog.show(mContext, null, "Creating group...");
}
#Override
protected String doInBackground(Void... params) {
String chatId = ServerUtilities.create();
if (chatId == null) return null;
try {
...
} catch (SQLException sqle) {}
return chatId;
}
#Override
protected void onCancelled() {
pd.dismiss();
}
#Override
protected void onPostExecute(String result) {
pd.dismiss();
if (result != null) {
Toast.makeText(mContext, "Group created " + result, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(mContext, "Group creation failed. Please retry later.", Toast.LENGTH_LONG).show();
}
}
}
In Dialog Fragment
To Start the async task you need context. In dialog Fragment you can get the context by calling getActivity(); or else you can get the context or activity reference in onAttach() lifecycle method of dialog fragment. Already parametrized constructor is there better to remove zero parametrized constructor.
new CreateGroupTask(getActivity()).execute();
(OR)
private Activity activity;
onAttach(Activity activity){
this.activity=activity;
//store this activity reference
}
//Then Call
new CreateGroupTask(activity).execute();
You can create an object of the class CreateGroupTask and execute wherever you want.
CreateGroupTask createGroupTask = new CreateGroupTask();
then
` if (which == 0){ AddContactDialog dialog2 = new AddContactDialog();
dialog2.show(getFragmentManager(), "AddContactDialog");
} else if (which == 1){
createGroupTask.execute();
// Or new CreateGroupTask().execute();
}`
try this and tell us if any error
What you are missing in AsyncTask is Context. you are using mContext in below code
pd = ProgressDialog.show(mContext, null, "Creating group...");
but you are not initializing that object in default constructor.
Use getActivity while calling task
new CreateGroupTask(getActivity()).execute();
Also remove following constructor from your code
public CreateGroupTask() {
}

keep TrayDialog open and submit the data

I have a dialog which extends TrayDialog to collect some data from user. I want to pass the values collected to another class without closing the dialog. If I override the okPressed() method, data will be passed back but window will be closed.
public class MyDialog extends TrayDialog {
public MyDialog(final Shell shell, final MyData mydata) {
super(shell);
this.shell = shell;
this.mydata = mydata;
}
#Override
protected void okPressed() {
if (!validateData()) {
return;
}
super.okPressed();
}
//rest of the code for text box, buttons in the dialog
}
final MyDialog myDialog = new MyDialog(new Shell(), this.mydata);
if (myDialog.open() == Window.CANCEL) {
return null;
}
//here get the data that user has entered in the dialog after they press ok
If you don't call super.okPressed() dialog will not be closed. Source:
protected void okPressed() {
setReturnCode(OK);
close();
}
And in order to pass data back on okPressed action, I would suggest to provide a callback to MyDialog. Something like this:
public interface MyCallback {
void okPressed(MyData data);
}
public class MyDialog extends TrayDialog {
public MyDialog(final Shell shell, final MyData mydata, MyCallback callback) {
super(shell);
this.shell = shell;
this.mydata = mydata;
this.callback = callback;
}
#Override
protected void okPressed() {
if (!validateData()) {
return;
} else {
callback.onPressed(data);
}
//super.okPressed();
}
MyCallback callback = new MyCallback() {
void okPressed(MyData data) {
// handle data
}
}
final MyDialog myDialog = new MyDialog(new Shell(), this.mydata, callback);
if (myDialog.open() == Window.CANCEL) {
return null;
}
In this case you would need to manually close dialog at some point. Also, Dialog will not block the execution thread, if you use setBlockOnOpen(false);

Categories

Resources