I have a method called getData() in an Activity that returns a String[]:
Example:
public class Strings{
public String[] getData(){
String[] data = {"one","two","three"};
return data;
}
}
My question is how to retrieve these items, because in another activity I want to put this into a SimpleAdapter list. I can call
String[] data = Strings.getData();
then have that as a variable that is technically the array, but I need to read out the items into the adapter. I know its probably simple but like I said, noob, haha.
For sharing data between different activity, I think you need to send that data with Intent before you change Activity
intent.putExtra("TheStrings", this.getStrings());
Related
I am a beginner in android studio, so please bear with me.
I've retrieved data from my intent in a recyclerview activity but I don't know how to pass it to its corresponding adapter class (recyclerview_adapter.java).
How should I start, does anybody have an example?
Thanks in advance.
you can just create a constructor inside adapter class with variable you want to pass and place a global variable by which you can use that variable(data).
class adapter{
// you can pass whole object or any kind of data here as well, just replace string with appropriate class name...
private String data;
// the data string will be set from your recycle activity...
public adapter(String data){
this.data = data;
}
// use the data string anywhere in adapter class...
}
I have a notification which contains a next button and a previous button. Now when I press any of the buttons in the notification the actions are received by the Broadcast receiver.
What my problem is that I am having trouble refreshing my recyclerview when either of the buttons are pressed.
I have been able to do it if I would set my adapter to static in the main class and call it in the broadcast receiver it works like this:
BroadCast Receiver Class:
public void getPlaylistItems(){
if (list != null){
list.clear();
}
SongsDatabase SongsDB = new SongsDatabase(contexts);
Cursor data = SongsDB .getSongs();
if(data.getCount() != 0){
data.moveToFirst();
do{
Songs myList = new (data.getString(0), data.getString(1), data.getString(2), data.getString(3), data.getString(4));
list.add(myList);
} while (data.moveToNext());
}
data.close();
VideoDB.close();
adapter.notifyDataSetChanged <--- This was made static in my Main Activity which contains the recyclerview
}
The problem with this solution is that it causes a memory leak in my app.
Now the question is how would I be able to refresh my recyclerview without making any variables static?
I believe you are creating an inner class inside your activity/fragment. To avoid making adapter static, you can create this broadcast receiver inside on your onCreate function instead.
Other approaches could be using an Event Bus,Interfaces or RxJava.
Yes you can without having a static reference to the adapter of your RecyclerView. You have the ContentObserver for that.
As I can see that, you are fetching the songs and the videos from the local database, you can easily put a content observer along with your database table. In that case, you need to create an Uri first which might look something like this.
public static final Uri DB_TABLE_SONGS_URI = Uri
.parse("sqlite://" + Constants.ApplicationPackage + "/" + DB_TABLE_SONGS);
// DB_TABLE_SONGS refers to the database table that you have for storing songs.
Now, while updating or inserting a new row in the songs table you need to notify the content observer like this.
context.getContentResolver().notifyChange(DBConstants.DB_TABLE_SONGS_URI, null);
Now use LoaderCallbacks and LoaderManager to fetch the data from songs table. Hence, in onCreateLoader function you need to register the content observer which will aid to recycle your RecyclerView without having any static reference to it.
This is a sample onCreateLoader function.
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new SQLiteCursorLoader(getActivity()) {
#Override
public Cursor loadInBackground() {
SongsDatabase SongsDB = new SongsDatabase(contexts);
cursor = SongsDB.getSongs();
this.registerContentObserver(cursor, DBConstants.DB_TABLE_SONGS_URI);
}
return cursor;
}
};
}
Do not forget to destroy the loader instance in onDestroy function.
getLoaderManager().destroyLoader(SONGS_QUERY_LOADER);
I have a fragment which summons a custom CursorAdaper and display it on a ListView
. The thing is I want to change the cursor by changeCursor() from another activity when I add new data, How can I get access to the CursorAdapter displayed on the fragment?
Essentially you have to pass data from one Activity to another and let the fragment of you choice receive the data (each fragment of a given Activity may get the Intent that started/restarted/resumed the Activity).
Consider this code
-- pass data:
String[] myListEntries = getNewListContents();
Intent updateList = new Intent(this, ActivityThatListFragmentBelongsTo.class);
updateList.putExtra("updated_list", myListEntries);
startActivity(updateList);
-- receive data (in fragment):
#Override
public void onResume() {
Intent wasStartedWithData = getActivity().getIntent();
String[] updatedList = wasStartedWithData.getStringArrayExtra("updated_list");
// pass updatedList to adapter
}
Now you might actually have more complicated data than an Array of Strings. In this case
you could create a class that implements 'Parcelable' (http://developer.android.com/reference/android/os/Parcelable.html) and call
putExtra(Parcelable parcel) / getParcelableExtra(String name) on the Intent.
I'm trying to change Roman's Nurik WizardPager so that in one of the steps display some data from my database.
I'm taking a Model and an UI from the library and I modify them so I can have a
DisplayOrderPage with a parameter ArrayList for my data
public DisplayOrderPage(ModelCallbacks callbacks, ArrayList<Salads> ord , String title) {
super(callbacks, ord, title);
}
and a DisplayOrderFragment which is going to display the data.
I can get an ArrayList with my data from my database in the MainActivity but I don't know how to pass that data to the SandwichWizardModel since it's not an Activity.
you can do one thing.. also pass the context of the activity as parameter. And declare a method in the activity which change the gui within a handler .. like this
in Activity
changeGUI(){
new Handler().post(new Runnable(){
// change gui
}
}
and call like
methodInCLasse(this, arrayList);
Problem: Activity A is a ListView that contains a ListAdapter, and clicking in any item of the adapter leads to activity B. Activity B has a button that fetches a new item (or several) from the web (using an AsyncTask) and adds it to the list displayed by activity A when pressed. That operation from B is not blocked by a ProgressDialog, so the user can move back to A before the AsyncTask that B started finishes fetching the data.
So I need a way of updating the adapter of A from B.
I have a class C with static data displayed in the ListView by A. When the button at B is pressed, it adds that value to C. That class also has the adapter from A as a static field, but I think that this leaks the memory from the Context, and that is bad. My first idea of fixing this was removing the static adapter from C and every time A onResume() (and if the data on the adapter is different from what I have at C), I load the data from C again into the adapter and notifyDatasetChanged(). Well, it works most of the time, but if the user goes back to A from B before B fetches the data from the web, then the adapter does not update, since the onResume() came before the data is fetched.
Question: Is there a better way of updating the adapter of A from B?
Don't save static references to the adapter. It will indeed leak memory and behave badly.
It appears I misunderstood the first time. Here is an updated answer:
First solution
The prettiest solution is to implement a content provider for the data storage and query that content provider in both A and B. Update the data in B using contentProvider.insert()
and read the data using contentProvider.query() returning for example a SQLiteCursor if it is backed by database or a MatrixCursor if you just save it in memory in the content provider.
The basic steps (without CursorLoader):
In onCreate of A you register yourself as a contentobserver using ContentResolver.registerContentObserver(uri, true, this) where uri is an URI using some scheme you set.
In onCreate of A you get the data by querying the contentprovider using ContentResolver.query(uri, projection, selection, selectionArgs, sortOrder) where projection, selection, selectionArgs and sortOrder can be what fits your contentprovider (maybe null). Uri refers to the data you want to query and is your choice.
When data is loaded in B you call ContentResolver.insert(). In insert of your contentprovider you call ContentResolver.notifyChange (Uri uri, null, null) where uri is the URI you used in step 1.
Implement onChange(boolean selfChange) in A and requery the content provider when it is called.
Note that you will not need to call registerContentObserver at all if you use CursorLoaders!
It will receive the new cursor in the loader since it has automatic requery when you notify change.
Second solution
A less pretty solution is to implement a singleton object that handles the data.
Something like:
Implement the class
public class DataHolder {
private static DataHolder sDataHolder;
private String data = ""; // Data represented by string.
public DataHolder getInstance() {
if (sDataHolder == null) {
sDataHolder = new DataHolder()
}
return sDataHolder;
}
private DataHolder() {} // Hidden constructor
public void setData(final String data) {
mData = data;
for (DataListener listener: mDataListeners) {
listener.onDataChanged(mData);
}
}
public void registerListener(DataListener listener) {
mDataListeners.add(listener);
}
public String unregisterListener(DataListener listener) {
mDataListeners.remove(listener);
}
public String getData() {
return mData;
}
public static interface DataListener {
public void onDataChanged(String data);
}
}
Make A implement DataListener
Read and update the data in onStart() of DataListener to make sure that it is set if the change was done when B was alive using DataHolder.getInstance().getData().
Register listener in A's onCreate/onStart using DataHolder.getInstance().registerListener(this); Let the listener update the data.
Unregister listener in A's onDestroy/onStop using DataHolder.getInstance().unregisterListener(this)
Set the data and signal any listener in B using DataHolder.getInstance().setData(data)
Also note that you can make the second solution fully thread safe by changing void registerListener() to synchronized String registerListenerAndGetValue() if you also make setValue synchronized.
Old answer based on a misunderstanding
My old answer for general result handling did not quite answer the question, but it was:
If you want to send data back to an activity A you should do the following:
Always start B with startActivityForResult (Intent intent, int requestCode)
Set the result when done in B using setResult (int resultCode)
Handle the result when you come back to A by implementing onActivityResult (int requestCode, int resultCode, Intent data)
As an addition you could add so you only fetch data in A the first time by doing it only if savedInstanceState == null in for example onCreate().
try calling mListView.invalidate();
**java-doc
Invalidate the whole view. If the view is visible, onDraw(android.graphics.Canvas) will be called at some point in the future. This must be called from a UI thread. To call from a non-UI thread, call postInvalidate().