No empty constructor: android class - java

My problem is, I am transferring two arrays between activities. with an return from the one to another Activity. There I am getting these two Activities by the constructor( I think ). Is this correct? Why I am getting the error: no empty constructor?
Here is my class where the Activites are coming from:
public PlanOutputActivity fetchallRoutes(String startStop, String endStop, String time) {
.
.
.
return new PlanOutputActivity(convertArray(),routenArray);
Here is my Activity where i wanna get these two Arrays:
public class PlanOutputActivity extends Activity {
Intent intent;
Object[][] routenArray;
String[][] itemsArray;
DatabaseHelperActivity mdbH;
public int RESULT_OK = 123;
public int REQUEST_OK = 456;
public PlanOutputActivity(String[][] itemsArray, String[][] routenArray){
setContentView(R.layout.planoutputlayout);
this.routenArray = routenArray;
this.itemsArray = itemsArray;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated constructor stub
super.onCreate(savedInstanceState);
}
public void getRoute() {
intent = getIntent();
mdbH = new DatabaseHelperActivity(this);
mdbH.fetchallRoutes(intent.getStringExtra("StartHaltestelle"),intent.getStringExtra("ZielHaltestelle"),intent.getStringExtra("Zeit"));
ListView lvList = (ListView)findViewById(R.id.ListOutput);
ArrayAdapter<DefineRouteActivity> adapter = new RouteAdapterActivity(this, route);
lvList.setAdapter(adapter);
lvList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
int gKennung = view.getId();
Intent intent = new Intent(getApplicationContext(),DetailOutputActivity.class);
intent.putExtra("Kennung",gKennung);
intent.putExtra("routenArray",routenArray);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
}

You can't create an instance of an Android Activity using new - it simply doesn't work.
The only ways to create an Activity are either when it is launched from the Apps launcher or if you call startActivity(...) (or one of the other methods such as startActivityForResult(...) etc).
Because of that you shouldn't ever create constructors for an Activity and you should never create public static fields or methods with the intention of accessing data or calling methods in an Activity from any other application class.
If you want to pass data from one Activity to another do it using the extras in an Intent or simply persist the data in SharedPreferences or a database. Alternatively create a 'helper' class to hold the data - using the Singleton pattern is quite common for this.

Related

Calling the Refresh() method which is in the main activity from another activity [duplicate]

This question already has answers here:
How to refresh listview in fragment when onbackpressed()
(4 answers)
Closed 1 year ago.
I'm developing an android app using java, but I have the problem below.
I have the main activity where there is a button "add" and a listview. When I click the add button, it will open another activity where I can add items to the listview. After adding this item, when I click the back button from the second activity, I want that the Refresh() method from the main activity to be executed to add this item directly to the listview in the main activity. I can't find a way to solve it. I tried to make this method as static but lot of errors appear, and the all the app is stopped. Also I tried to create new instance of the main activity in the onBackPressed() method of the second activity, but the app has also stopped. Anyone can help me to solve this problem?
Thank you.
Read this: https://developer.android.com/training/basics/intents/result then add a call to your refresh method in your MainActivity after you get a result back indicating that the second activity is done.
I believe that the following working example shows how you can accomplish what you want :-
MainActivity (the initial activity) :-
public class MainActivity extends AppCompatActivity {
public static final int ACTIVITY1_REQUEST_CODE = 999;
public static final String EXTRA_MYARRAY = "extra_myarray";
private Button next;
private ListView listView;
ArrayAdapter<String> adapter;
ArrayList<String> myarray = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
next = this.findViewById(R.id.next);
listView = this.findViewById(R.id.listview);
// Prepare the Button's onClickListener to start the other activity
next.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(view.getContext(),Activity2.class);
// prepare to pass the data to the other activity
i.putExtra(EXTRA_MYARRAY,myarray);
// Start the other activity
startActivityForResult(i,ACTIVITY1_REQUEST_CODE);
}
});
// Prepare the data
myarray.add("a");
myarray.add("b");
myarray.add("c");
// Output data to the log (to show what happens)
refresh(myarray,"INITIAL", false);
}
// Prepare to receive and handle the modified data when returning from other activity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTIVITY1_REQUEST_CODE && resultCode == RESULT_OK) {
myarray.clear();
for(String s: data.getStringArrayListExtra(EXTRA_MYARRAY)) {
myarray.add(s);
}
refresh(data.getStringArrayListExtra(EXTRA_MYARRAY),"RESUMED",true);
}
}
/**
* Refresh
* #param modifiedData The modified data to be applied (see modify) as an ArrayList<String>
* #param tagExtra String used to indicate where the refresh was called from
* #param modify flag to indicate whether or not to rebuild the data
* if coming from the this activity then clear and add would
* empty the array and add nothing
*/
private void refresh(ArrayList<String> modifiedData, String tagExtra, boolean modify) {
if (modify) myarray.clear();
for(String s: modifiedData) {
if (modify) myarray.add(s);
Log.d("MA_" + tagExtra,"Value is " + s);
}
refreshListView();
}
private void refreshListView() {
if (adapter == null) {
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,myarray);
listView.setAdapter(adapter);
} else {
adapter.notifyDataSetChanged();
}
}
}
Activity2 the invoked/2nd activity (which modifies the list and returns that modified list to the parent when the button is clicked) :-
public class Activity2 extends AppCompatActivity {
private Button finish;
private ArrayList<String> myarray = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_2);
finish = this.findViewById(R.id.finish);
// Prepare the Button's onCLickListener
finish.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent();
// Prepare to return the data
i.putExtra(MainActivity.EXTRA_MYARRAY,myarray);
// Indicate that all is OK
setResult(RESULT_OK,i);
// Finish this activity and thus pass control back to the parent activity
finish();
}
});
// Modify the data
myarray = this.getIntent().getStringArrayListExtra(MainActivity.EXTRA_MYARRAY);
myarray.add("d");
}
}
Comments should explain the code
Note this method does use the deprecated (startActivityForResult) so you may wish to consider looking at Getting a result from an activity
Result
When run the App displays :-
Clicking the NEXT button takes you to the 2nd Activity :-
Clicking the FINISH button (the activity adds a new element) returns to the MainActivity which is now :-
i.e. the new element is displayed accordingly in the ListView

Imitate 'onActivityResult' inside an Adapter of RecyclerView

I have a RecyclerView which items' contain a button that launches an activity using startActivityForResult. The onClick method was implemented inside the adapter, and onActivityResult from the fragment that contains the RecyclerView was not called upon returning from the new activity. As I learned, this is to be expected, because startActivityForResult was not called from this fragment.
The closest thing to a solution I found was this:
onActivityResult inside a RecyclerView.Adapter not being used
But when trying to use an interface to implement the onClick method, I now face a new problem: I can't call the onClick method inside the adapter, although it's implemented inside the activity, because the Adapter's context is static, and the method is non-static.
Below are some code portions to explain better the current situations. I'm in desperate need for an alternative solution, I really searched through and through. Thanks.
The fragment implements the interface:
public class EditableOffersListFragment extends Fragment implements OnClickButtonListener { ...
#Override
public void onClickButton(View v, int position, ArrayList<Offer> offers) {
Offer from_item = offers.get(position);
Intent intent = new Intent(getActivity(), OfferDetailsPopupActivity.class);
intent.putExtra("new", false);
intent.putExtra("offer_fromRecycler", from_item);
getActivity().startActivityForResult(intent, HTZ_ADD_OFFER);
}
...}
The interface (in a seperate file):
public interface OnClickButtonListener {
void onClickButton(View v, int position, ArrayList<Offer> offers);
}
And inside the adapter:
mEditOfferButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
OnClickButtonListener.onClickButton(v, getAdapterPosition(), mOffers);
}
});
I think the problem you're currently facing is that you're calling startActivityForResult from the Activity containing the current fragment rather than the Fragment itself. So using this or just plainly calling the startActivityForResult will call it from the Fragment instead of the Activity and this fragment will be callbacked with the result from the other Activity.
public class EditableOffersListFragment extends Fragment implements OnClickButtonListener { ...
#Override
public void onClickButton(View v, int position, ArrayList<Offer> offers) {
Offer from_item = offers.get(position);
Intent intent = new Intent(getActivity(), OfferDetailsPopupActivity.class);
intent.putExtra("new", false);
intent.putExtra("offer_fromRecycler", from_item);
startActivityForResult(intent, HTZ_ADD_OFFER); // <--- Note that this line has changed
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// Do your result handling here
}
}
Ok, finally solved it.
What worked was adding a OnClickButtonListener member to the Adapter, which is passed from the Fragment in the Adapter's constructor (the Fragment is implementing OnClickButtonListener so I just passed 'this' to the constructor).
That way, all of the actions performed in the adapter are on an instance of OnClickButtonListener and the static/non-static problem was solved.

How Can I use Same Adapter of a GridView on Different activities

Let say I have two Activities, Activity A and Activity B.
Activity A displays a list of images using the Adapter Z.
When user clicks on any image in Activity A, they will be taken to Activity B to show the full image. I'm passing image path and grid position to Activity using Intent.
Now in Activity B, I place a delete button which should delete the imagepath from the gridview adapter.
Problem is:
How can I access the Activity A adapter in activity B to call remove(position) method in my adapter.
So I can call notifyDataSetChanged in onResume of Activity A to update the gridview images.
Activity A
MyGridView = (GridView) findViewById(R.id.gridview);
adapter = new MyAdapter(this);
MyGridView .setAdapter(adapter );
Intent fullImageActivity = new Intent(getApplicationContext(), ActivityB.class);
fullImageActivity.putExtra("position", position);
fullImageActivity.putExtra("path", mediaPath);
startActivity(fullImageActivity);
Activity B
Intent i = getIntent();
// I'm getting position and path from setOnItemClickListener
position = i.getExtras().getInt("position");
path = i.getExtras().getString("path");
// I want to remove path from my adapter after clicking delete button in Activity B
Adapter
public ArrayList<String> images;
public void remove(int position){
images.remove(position);
}
use startActivityForResult.
Intent fullImageActivity = new Intent(getApplicationContext(), ActivityB.class);
fullImageActivity.putExtra("position", position);
fullImageActivity.putExtra("path", mediaPath);
startActivityForResult(fullImageActivity, 2);
check if deleted at particular position in Activity B . here I override onBackPressed() (For Ex.) method
public void onBackPressed(){
super.onBackPressed()
Intent intent=new Intent();
intent.putExtra("isdeleted",true);
intent.putExtra("pos",position);
setResult(2,intent);
finish();
}
Handle it in onActivityResult in Activity A.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
// check if the request code is same as what is passed here it is 2
if(requestCode==2)
{
if(data.getBooleanExtra("isdeleted")){
remove from position array and notify dataset change. // pos = data.getIntExtra("pos")
}
}
}
Sorry for TYPO.
The key here is that you need to share the data and not really the adapter.
Using a singleton
You can use a singleton class to hold the image data and then access the same in both the activities. This ensures sync between both activities at all times.
Singleton Class
public class ImageData{
private ArrayList<ImageModel> mDataOfImages;
private ImageData mHelperInstance;
private ImageData(){
//private constructor to ensure singleton
}
public static ImageData getInstance(){
// return an ImageData instance according to your implementation
// of singleton pattern
}
private void setData(ArrayList<ImageModel> newData){
this.mDataOfImages = newData;
}
private void removeImage(int position){
if(this.mDataOfImages !=null && this.mDataOfImages.size() > position){
mDataOfImages.remove(position);
}
}
}
Activity A
private void saveImageData(ArrayList<ImageModel> data){
if(data !=null){
if(mAdapter !=null){
mAdapter.setData(data);
}
}
}
//Call notifydatasetchanged when activity is opened again
#Override
protected void onStart() {
if(mAdapter !=null){
mAdapter.notifyDataSetChanged();
}
}
MyAdapter
public void setData(ArrayList<ImageMode> newData){
if(newData !=null){
ImageDataSingleton.getInstance().setData(newData);
notifyDataSetChanged();
}
}
Activity B
Use the singleton class to display images in Activity B. Because you are using the model array list, you can easily implement right/left swipes and delete multiple images.
//Delete a image
private void deleteImage(){
ImageDataSingleton.getInstance().removeImage(getCurrentPosition());
// Rest of deletion handling like moving to right or left image
}
I think that you should build your remove method in activity A and be sure that it is static:
public static void remove(int position){
images.remove(position);
}
now you can call it from activity B like this:
ActivityA.remove(position);
I think this will work.

How to pass an id into parceable?

I am trying to implement parceable to pass data to the next screen so on my home activity I am calling a bunch of methods (oncreate, etc.) now I am trying to take from the query made in the oncreate and pass it into the next screen on a onclick, however prior to the onclick I want to add the information by telling parceable to take care of it... However I am not sure how I can pass the information from the onclick into a new class that implements Parceable...
Here is my code attempt: (not sure what I pass into the extra, documentation is lacking on android website)
#Override
public void onClick(View v) {
if (v == add_new_dictionary) {
Log.e("clicked add button", "adding the dictionary... ");
// no return true because it is void on intents
Intent add_new_dictionary_intent = new Intent(MainActivity.this,
add_new_dictionary.class);
startActivity(add_new_dictionary_intent);
} else {
// used to get tag for dictionary
Object tag = v.getTag();
//call parceable
SendIdOfDictionary(tag);
// start new intent based on the tag -
Intent new_dictionary_view = new Intent(MainActivity.this,
dictionary_view.class);
new_dictionary_view.putExtra("d_id", WhatAmISupposeToPassInHere);
startActivity(new_dictionary_view);
}
// parceable is faster than serialization - create class to implement it
}
private void SendIdOfDictionary(Object tag) {
class ParceDictionaryData implements Parcelable {
private String tag;
/* everything below here is for implementing Parcelable */
// 99.9% of the time you can just ignore this
public int describeContents() {
return 0;
}
// write your object's data to the passed-in Parcel
public void writeToParcel(Parcel out, int flags) {
out.writeString(tag);
}
// this is used to regenerate your object. All Parcelables must have
// a CREATOR that implements these two methods
public final Parcelable.Creator<ParceDictionaryData> CREATOR = new Parcelable.Creator<ParceDictionaryData>() {
public ParceDictionaryData createFromParcel(Parcel in) {
return new ParceDictionaryData(in);
}
public ParceDictionaryData[] newArray(int size) {
return new ParceDictionaryData[size];
}
};
// example constructor that takes a Parcel and gives you an object
// populated with it's values
private ParceDictionaryData(Parcel in) {
tag = in.readString();
}
}
Use a bundle, no need for a Parceable here.
Add it to the Intent that starts your 2nd Activity:
Intent i = new Intent();
i.putExtra("tag", yourTag);
Then get it with
getIntent().getExtras().getString("tag");
to pass the values
public void onClick(View view) {
//Launching All products Activity
Intent in = new Intent(getApplicationContext(), ViewMap.class);
// sending address to next activity
in.putExtra("address",strAdd);
// starting new activity and expecting some response back
startActivityForResult(in, 100);
}
and to receive the value
Intent i = getIntent();
// getting product id (pid) from intent
Bundle extras = getIntent().getExtras();
if (extras != null) {
adress=extras.getString("address");
}

Trying to access my parcelable object sent from one activity to another

This is my onitemclick which I use for when I want to start the new activity (Called DynamicEvents), and at this point I want to send my object of type Clubs that comes from db.get(map.get(position));
I now want to be able to access the object that I have sent across in my DynamicEvents Class
This is my onItemClick method from my ListSample Class
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
Clubs mymeeting = db.get(map.get(position));
Intent i = new Intent();
Bundle b = new Bundle();
b.putParcelable("my meeting", mymeeting);
i.putExtras(b);
i.setClass(ListSample.this, DynamicEvents.class);
startActivity(i);
}
});
and at the moment I have no code in my DynamicEvents class, I have tried a few things, however most seem a bit too long winded and use .getIntent which eclipse wants me to write my own method for?
For my DynamicEvents class what should I be implmenting?
Any sample code of being able to access the object or any help would be appreciated.
Thanks
Thought I would add this, this is an example of the code I have tried.
and as i said it uses .getIntent
Bundle b = this.getIntent().getExtras();
if(b!=null)
meeting = b.getParcelable("my meeting");
In your Dynamic events activity. getIntent is a method of your activity class
http://developer.android.com/reference/android/app/Activity.html#getIntent()
public class DynamicEvents extends Activity
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.mylayout);
Bundle b = getIntent().getExtras();
Meeting meeting = b.getParcelable("my meeting");
}
}

Categories

Resources