I saw other related post to it, but those posts couldn't solve my problem. I am making a Time Table app. I have made a constructor of my TimeTable
class that I will use in my Log
class.
From the TimeTable
class, I want to get the value of strFileName
and have this value assigned to a particular element of the logs
ArrayList that is in the Log
class. logs
ArrayList is an ArrayList of log
, where each log
is cardView and a log
has a TextView to which I want to assign strFileName
from TimeTable
.
Here is the TimeTable
Class -
package com.example.timetable;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class TimeTable extends AppCompatActivity implements saveFolderDialog.saveFolderDialogListener{
private RecyclerView recyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager layoutManager;
Button addBtn;
TextView day;
TextView date;
ArrayList<row> rows = new ArrayList<>();
private int indexOfEachRow;
String strFileName;
public TimeTable() {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.time_table);
setupAppElements();
createRecyclerView();
addEmptyRow();
indexOfEachRow = rows.get(rows.size() - 1).getIndex();
addBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//check whether the last row's credentials are empty or not
if(rows.get(rows.size()-1).getTasksName().matches("") || rows.get(rows.size()-1).getHours() == 0) {
Toast.makeText(TimeTable.this, "Fill out previous row's content", Toast.LENGTH_SHORT).show();
return;
}
int totalHours = 0;
for(int i=0; i < rows.size(); i ){
totalHours = totalHours (rows.get(i).getHours());
}
if (totalHours <= 24) {
addEmptyRow();
mAdapter.notifyItemInserted(rows.size());
} else {
Toast.makeText(TimeTable.this, "Total hours have exceeded 24 hours", Toast.LENGTH_SHORT).show();
}
}
});
}
public void createRecyclerView(){
recyclerView = (RecyclerView) findViewById(R.id.list);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
mAdapter = new TimeTableAdapter(rows, TimeTable.this);
recyclerView.setAdapter(mAdapter);
}
public void addEmptyRow(){
rows.add(new row());
for(int i = 0; i < rows.size(); i ) {
rows.get(rows.size() - 1).setIndex(indexOfEachRow i);
}
rows.get(rows.size() - 1).setTasksName("");
}
public void setupAppElements(){
addBtn = findViewById(R.id.add);
day = findViewById(R.id.day);
date = findViewById(R.id.date);
}
@Override
public boolean onCreateOptionsMenu(Menu menu){
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch(item.getItemId()){
case R.id.collectData:
//connect the total hours with the pie chart
savePopUpWindow();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void savePopUpWindow(){
saveFolderDialog sFD = new saveFolderDialog();
sFD.show(getSupportFragmentManager(),"save folder dialogue");
}
public String getStrFileName() {
return strFileName;
}
@Override
public void assignFolderName(String fileName) {
strFileName = fileName;
}
}
The last method in the above class, assignFolderName
, come from another class called saveFolderDialog
and here is the code for it -
package com.example.timetable;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatDialogFragment;
public class saveFolderDialog extends AppCompatDialogFragment {
private AlertDialog.Builder dialogBuilder;
private saveFolderDialogListener listener;
private EditText fileName;
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
dialogBuilder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.save_popup_window, null);
dialogBuilder.setView(view)
.setTitle("")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.setPositiveButton("Save", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String strFileName = fileName.getText().toString();
listener.assignFolderName(strFileName);
}
});
fileName = view.findViewById(R.id.fileName);
return dialogBuilder.create();
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
try {
listener = (saveFolderDialogListener) context;
}
catch (ClassCastException e){
throw new ClassCastException(context.toString()
"must implement the saveFolderDialogListener >:(");
}
}
public interface saveFolderDialogListener{
void assignFolderName(String fileName);
}
}
Here is the Log
class -
package com.example.timetable;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class Log extends AppCompatActivity {
private RecyclerView recyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager layoutManager;
ArrayList<logsRow> logs;
public Log (ArrayList<logsRow> logs){
this.logs = logs;
}
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.log_sheet);
createRecyclerView();
addLog();
}
public void createRecyclerView(){
recyclerView = (RecyclerView) findViewById(R.id.log_sheet);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
mAdapter = new LogAdapter(logs, Log.this);
recyclerView.setAdapter(mAdapter);
}
public void addLog(){
TimeTable timeTable = new TimeTable();
String fileName = timeTable.getStrFileName();
logs.add(new logsRow(fileName));
}
}
The problem arises in my addLog
method in my Log
class. I am getting an error and here is the stack trace for it -
2022-06-25 11:52:31.909 1640-1640/com.example.timetable E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.timetable, PID: 1640
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.timetable/com.example.timetable.Log}: java.lang.InstantiationException: java.lang.Class<com.example.timetable.Log> has no zero argument constructor
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3545)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3792)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2210)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Caused by: java.lang.InstantiationException: java.lang.Class<com.example.timetable.Log> has no zero argument constructor
at java.lang.Class.newInstance(Native Method)
at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:95)
at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
at android.app.Instrumentation.newActivity(Instrumentation.java:1273)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3532)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3792)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2210)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
I don't understand why I am getting such an error because I have made a zero argument constructor and I need it to be used in another class.
CodePudding user response:
Delete:
public Log (ArrayList<logsRow> logs){
this.logs = logs;
}
Never implement a constructor on a subclass of AppCompatActivity
.
Also, delete:
TimeTable timeTable = new TimeTable();
Never create an instance of a subclass of AppCompatActivity
. The system creates instances when that activity should be shown, such as in response to a startActivity()
call.