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.
Related
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
The codes are messy at this point since I've been going back and forth so much. Every time user clicks the yes/no button I want the results of counts the button has been clicked to display in another activity. I also want to reset the number of clicks from the second activity as well. All that's needed in the first activity is the question and the yes/no button. Is this possible? Thanks in advance.
public class MainActivity extends AppCompatActivity {
private static final String TAG = "SurveyActivity";
private static final String YES_INDEX = "yes votes";
private static final String NO_INDEX = "no votes";
Button mYesButton;
Button mNoButton;
Button mResetButton;
TextView mSurveyQuestion;
private int yesVoteCount = 0;
private int noVoteCount = 0;
private int resetVotes = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Use res ID to retrieve inflated objects and assign to variables
mYesButton = findViewById(R.id.yes_button);
mNoButton = findViewById(R.id.no_button);
mResetButton = findViewById(R.id.reset_button);
mSurveyQuestion = findViewById(R.id.survey_question);
mYesButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
addVote();
}
});
mNoButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
addVote();
}
});
// Resetting vote count
mResetButton.setOnClickListener(new View.OnClickListener() {
#Override
***Should this supposed to be in the second activity?
}
});
}
private void addVote() {
if (mYesButton.isPressed()) {
yesVoteCount++;
} else if (mNoButton.isPressed()) {
noVoteCount++;
}
}
In your main activity
btnShowResut.setOnClickListener(new View.OnClickListener() {
#Override
// Create intent for going to another activity
Intent intent = new Intent(this, AnotherActivity.class);
// Put counts datas to intent
intent.putExtra("yesCountKey", yesVoteCount);
intent.putExtra("noCountKey", noVoteCount);
// NEW : Go to another activity by calling it instead
// REQUEST_CODE is an integer variable
startActivityForResult(intent, REQUEST_CODE);
}
});
In Another activity, you can retrieve datas in onCreate method like this and send action to clear counts of your main activity.
...
onCreate(...){
...
// Retrieve datas from intent
int yesCount = getIntent().getIntExtra("yesCountKey", 0);
int noCount = getIntent().getIntExtra("noCountKey", 0);
mResetButton.setOnClickListener(new View.OnClickListener() {
#Override
// Send a boolean to main activity for clearing votes
Intent intent = new Intent();
intent.putExtra("resetVotes", true);
setResult(RESULT_OK, intent);
// Close second activity
finish();
}
});
}
Finally in the main activity override this method and clear votes
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
if(requestCode == 2000 && resultCode == RESULT_OK){
boolean reset = data.getBooleanExtra("resetVotes", false);
if(reset){
yesVoteCount = 0;
noVoteCount = 0;
}
}
}
As the mentioned above, you can get the counts by using intent extras.
However if you want to reset the counts in in the second activity you might want to start the Activity B as startActivityForResult() see the Android documentation here.
Then when Activity B end you can reset the counts in the call back method onActivityResult().
If you don't want to do it like this the next best way might be to reset the counts onResume() of Activity A so that when you return to the activity you will start with fresh counts. See life cycle documentation here
I have a fragment which is present in Bottom Navigation Activity. The Fragments contain the custom recyclerview. There is a comment button when i press it opens another activity for comments. Below is in the RecyclerView adapter.
viewholder.commentlay.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
//commenttofragment.clear();
Intent comment = new Intent(fp, com.fooddoof.fuddict.comment.class);
int id = dusers.get(position).getId();
int comcount = dusers.get(viewholder.getAdapterPosition()).getCommentcount();
comment.putExtra("id",id);
comment.putExtra("ownerid",userid);
comment.putExtra("maincommentposition",position);
comment.putExtra("commentcountonposition", comcount);
fp.startActivityForResult(comment,1);
}
});
In Comment activity after doing some tasks I need to send some values to this fragment. So I Override the OnBackPressed method. I have created a method in Fragment to receive it.
#Override
public void onBackPressed()
{
Bundle args = new Bundle();
args.putInt("maincommentcount",maincommentcount);
args.putInt("maincommentposition", maincommentposition);
FolowersPost f = new FolowersPost();
f.getdatafromcomment(args);
finish();
}
I receive it like below in Fragment.
public void getdatafromcomment(Bundle args)
{
int count = args.getInt("maincommentcount");
int p=args.getInt("maincommentposition",999999999);
Log.e("Shiva","count--->"+count+"p--->"+p);
}
The Values are received but I need to access the arraylist in Fragement which is passed in Adapter for displaying the recyclerView. But I am not able to access it while I am coming back to fragment which is present in the method under OnCreateView. I tried with OnResume to access it but works for some time only. I have declared the Arraylist as global variable also.
You are already using startActivityForResult. now you just need to use onActivityResult.
But you just need to start activity from fragment instead of from adapter.
onClick from fragment:
Intent comment = new Intent(getActivity(), com.fooddoof.fuddict.comment.class);
startActivityForResult(comment, 1);
onBackPressed in your comment activity:
#Override
public void onBackPressed() {
Intent returnIntent = new Intent();
returnIntent.putExtra("maincommentcount",10);
returnIntent.putExtra("maincommentposition",20);
setResult(Activity.RESULT_OK,returnIntent);
finish();
// super.onBackPressed();
}
onActivityResult in fragment:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if (resultCode == Activity.RESULT_OK) {
int mMaincommentcount = data.getIntExtra("maincommentcount", 0);
int mMaincommentposition = data.getIntExtra("maincommentposition", 0);
System.out.println("mMaincommentcount = " + mMaincommentcount + ", mMaincommentposition = " + mMaincommentposition);
}
}
}
I want to change the background color of Main activity by using spinner in second Activity. I have already created one button and it goes to second activity and in this second activity I have created spinner which consist of which color should be in the main activity. After choosing the color, the button I created will change the background color and will be back to first activity.
From what I understand, you need the ActivityForResult behavior.
You use startActivityForResult to fire the Intent from your first activity to your second, along with a request code.
You use an Intent and setResult to send data from your second activity back to your first.
You override onActivityResult in your fist activity to get and use your data.
Sample code:
public class FirstActivity extends Activity {
private static final int PICK_COLOR_REQUEST = 1001;
...
private void pickColor() {
Intent pickColorIntent = new Intent(this, SecondActivity.class);
startActivityForResult(pickColorIntent, PICK_COLOR_REQUEST);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PICK_COLOR_REQUEST && resultCode == Activity.RESULT_OK) {
int color = data.getIntExtra("color");
/* use the color */
}
}
}
public class SecondActivity extends Activity {
...
private void onColorPicked(int color) {
Intent dataIntent = new Intent();
dataIntent.putExtra("color", color);
setResult(Activity.RESULT_OK,returnIntent);
finish();
}
}
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.