Adjust RealmResult without querying - android

I'm using a simple instance of RealmRecyclerViewAdapter to handle displaying MyObjects:
public class MyObjectsAdapter extends RealmRecyclerViewAdapter<MyObject, MyObjectsAdapter.ViewHolder> {
public interface Listener {
void onMyObjectClicked(Long myObjectId);
}
private Context context;
private Listener listener;
public MyObjectsAdapter(Context context, OrderedRealmCollection<MyObject> data, Listener listener) {
super(context, data, true);
this.context = context;
this.listener = listener;
}
... // Rest of the code.
Although this works for simple queries, I have one filter that is too complex for a realm query, so I'll have to filter myself by looping the results. But since I cannot "remove" an object from RealmResults (as it removes it from the realm), I would need to work with a List, which means I would have to rewrite the adapter.
My question is, is there a way to adjust RealmResult in a way that is not based on a realm query?

Write out what #EpicPandaForce suggests.
Add an extra field (hour) to your model class:
class MyObject extends RealmObject {
private Date timestamp;
private int hour;
public setTimestamp(Date timestamp) {
setHour(timestamp.getHours());
this.timestamp = timestamp;
}
// ...
}
You can now use hour in your queries.

Related

Passing objects between fragments using parcelable in kotlin

How do you do that? I have the object class implementing parcelable but i don't know what to do for sending the object from one fragment to another one. Help me please.
You can use the navGraph to share data between fragments.It's easy.
Sharing data between fragments is always painful, as both fragments need to define same interface description and the owner activity must bind two together.
And also need to handle the conditions like other fragment not created or not visible
But with new ViewModel, our life become easy to deal with fragment communication. All we have to do is just create a common ViewModel using the activity scope to handle the communication.
Let’s take an example where as in one fragment we need to show list of news articles , and another to show details of the selected news article.
Step1:- Create the Article model class.
public class Article {
private int articleID;
private String articleName;
private String details;
public int getArticleID() {
return articleID;
}
public void setArticleID(int articleID) {
this.articleID = articleID;
}
public String getArticleName() {
return articleName;
}
public void setArticleName(String articleName) {
this.articleName = articleName;
}
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}
}
Step2:- Create a ArticleViewModel which holds the objects.
public class ArticleViewModel extends ViewModel {
private LiveData<List<Article>> articleList;
private final MutableLiveData<Article> selectedArticle = new MutableLiveData<Article>();
public MutableLiveData<Article> getSelectedArticle() {
return selectedArticle;
}
public void setSelectedArticle(Article article) {
selectedArticle.setValue(article);
}
public LiveData<List<Article>> getArticleList() {
return articleList;
}
public void loadArticles() {
// fetch articles here asynchronously
}
}
Step3:- Create a ArticleListFragment which take care of your list.
public class ArticleListFragment extends Fragment {
private SharedViewModel model;
public void onActivityCreated() {
ArticleViewModel model = ViewModelProviders.of(getActivity()).get(ArticleViewModel.class);
listItemSelector.setOnClickListener(article -> {
model.setSelectedArticle(article);
});
}
}
Step4:- Create your ArticleDetailFragment to show details of article
public class ArticleDetailFragment extends LifecycleFragment {
public void onActivityCreated() {
ArticleViewModel model = ViewModelProviders.of(getActivity()).get(ArticleViewModel.class);
model.getSelectedArticle().observe(this, { article ->
// update UI
});
}
}
If you observe, both fragments are using getActivity() while getting the ViewModelProviders. Means both fragments receive same ArticleViewModel instance, which is scoped to your parent Activity.
Its just that simple and we get more benefits like
Your Activity no need to worry about this communication
Even one fragment get destroyed, other one use the data in ViewModel.
Happy coding :)

Use RxJava in order to parse an item and create a new one from the previous

I have the following Object and i want to use RxJava in order to create a new object. The logic behind this is that each article has a lot of comments. And it finds the correct comments using the ArticleData.commentId and the Comment.id.
public class ArticlesResponse {
public List<ArticleData> articles;
public List<Data> comments;
}
public class Data {
public int id;
public String link;
public String title;
public String author
public String body;
}
public class ArticleData extends Data {
public List<int> commentId;
}
So how can i use Rxjava in order to create the following object
public class Article extends Data {
public List<Comments> comments;
}
public class Comments extends Data {
// comments will have more attributes in the feature
// so use a seperate object
}
I know that i have to use the flapMap and the filter in order to parse the "ArticleResponse" but i don't know how to put all this together.
Furthermore the "ArticleResponse" is being generated from a json which i got from Retrofit, so i guess it will be better to use RxJava since i already have the Observable instead of putting nested for's inside my Callback.
I assume you means that articlesResponse.comments is a list contains all Comments of these all ArticleData, although I don't think wrap these data together and do the map operation in client is a good idea, this job should be done at server.
And I think maybe your ArticlesResponse's comments field should be a List<Comments>.
With these assumption, the code below may do the job you want (I put them in a TempTest class, and define an interface you described, and mock it to pass javac compile, and I also use Java 8 lambda grammar for code simplicity).
public class TempTest {
public static class Data {
public int id;
public String link;
public String title;
public String author;
public String body;
}
public static class ArticleData extends Data {
public List<Integer> commentId;
}
public static class Comments extends Data {
// comments will have more attributes in the feature
// so use a seperate object
}
public static class ArticlesResponse {
public List<ArticleData> articles;
public List<Comments> comments;
}
public class Article extends Data {
public List<Comments> comments;
}
public interface TestInterface {
Observable<ArticlesResponse> getArticle();
}
public static Comments findCommentWithId(int commentId, List<Comments> comments) {
for (Comments comment : comments) {
if (comment.id == commentId) {
return comment;
}
}
return null;
}
#Test
public void simpleTestcase() {
// assume you means that articlesResponse.comments is a list contains all Comments of these
// all ArticleData, although I don't think wrap these data together and do the map operation
// in client is a good idea, this job should be done at server
TestInterface testInterface = mock(TestInterface.class);
testInterface.getArticle().map(articlesResponse -> {
List<Article> result = new ArrayList<>();
// for each ArticleData in articlesResponse.articles
for (ArticleData articleData : articlesResponse.articles) {
// get all Comments from articlesResponse.comments
Article article = new Article();
// ... copy Data field from articleData to article
article.comments = new ArrayList<>();
for (Integer id : articleData.commentId) {
Comments comment = findCommentWithId(id, articlesResponse.comments);
if (comment != null) {
article.comments.add(comment);
}
}
result.add(article);
}
return result;
}).subscribe(articles -> {
for (Article article : articles) {
System.out.println(article);
}
});
}
}
Kind of confused at what your actual question is, so hopefully this helps. Retrofit can return an Observable for you, which should make RxJava integration easy. For example, in your service you could make:
#GET(<your endpoint>)
Observable<ArticlesResponse> getArticles();
And call it like:
<yourService>.getArticles()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedules.mainThread())
.subscribe() // manipulate how you want

bind custom object and view in the LinkedList or other container

I have my own class Order with many fields in it. I put LinkedList of them to the ListView with the custom ArrayAdapter. But I need to bind each order object with corresponding View of listView. I tried to implement getChildView() method of the listView but it doesn't work properly for me. Tell me please how can I implement robust and fast solution for this? SHould I use LinkedList for this? Or should I create my own data container? Besides, adding one more View field to the Order object seems to me like perfomance decreasing.
I solved this issue by HashMap using. I use singletone pattern for hashmap creating and using:
public class OrdersViewMapSingletone {
Map<Order, View> arrayList;
private static OrdersViewMapSingletone instance;
private OrdersViewMapSingletone()
{
arrayList = new HashMap<Order,View>();
}
public static OrdersViewMapSingletone getInstance(){
return instance;
}
public static void initInstance()
{
if (instance == null)
{
instance = new OrdersViewMapSingletone();
}
}
public Map<Order, View> getOrderViewMap()
{
return arrayList;
}
#Override
public String toString()
{
return getOrderViewMap().toString();
}
}
and in my OrderAdapter:
Map<Order, View> orderViewMap = OrdersViewMapSingletone.getInstance().getOrderViewMap();
add items in the getView() method:
orderViewMap.put(order,row);
and this method for getting items in the activity:
public View getMapedView(Order order)
{
return this.orderViewMap.get(order);
}
worked good for me. Perfomance is much better than ArrayList using.

Android ListView AdddAll problem

hi i am Using ArrayAdapter in ListView with custom Class object,HERE IS MY CODE
private static class NewsDetailAdapter extends ArrayAdapter<clsNewsItem>
{
private final Activity context;
List<clsNewsItem> newsList = null;
public NewsDetailAdapter(Activity context, ArrayList<clsNewsItem> clsNewsObjects) {
super(context, R.layout.listview_cell, clsNewsObjects);
this.context = context;
this.newsList = clsNewsObjects;
}
public void clear()
{
newsList.clear();
}
while i am working with this code AdapterObj.NotifyDatasetchanged() not working Due to i have not implemented addAll() method for this class,i cant understand how to write this Method so how can i Write Add All method for this ArrayAdaper class..can Any one help me please
Do you have specific need for subclassing? If you need to have some logic better have one ArrayAdapter as member instance and proxy its methods. Because the original ArrayAdapter already has all these methods readily available

Implementing Parcelable Class That Requires Context

I'd like for my data class to implement Parcelable so it can be shared between Activities, however it also needs reference to Context so the fields can be saved to SQLiteDatabase.
This however is a problem since Parcelable.Creator method createFromParcel only has one parameter Parcel.
public abstract class Record implements Parcelable {
protected Context context;
protected String value;
public Record(Context context) {
this.context = context;
}
public Record(Parcel parcel) {
this.value = parcel.readString();
}
public void save() {
//save to SQLiteDatabase which requires Context
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int flag) {
parcel.writeString(value);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public Record createFromParcel(Parcel parcel) {
return new Record(in);
}
public Record[] newArray(int size) {
return new Record[size];
}
};
}
How can a class that implements Parcelable also reference Context so it save to SQLiteDatabase?
The Parcelable interface is like the Java interface Serializable. Objects which implement this interface should be serializable. This means it should be possible to transform the object to a representation which could be saved in a file e.g.
It is easily possible for a string, int, float or double etc, because they all have a string representation. The Context class is clearly not serializable and not parcelable, because it can be an Activity for example.
If you want to save the state of your activity to a database, you should find another way to do that.
Your Record class probably doesn't really need access to the SQL database. The reason for it is exactly the problem you have now: it's very difficult to inject the Context back into each Record.
Perhaps a better solution would be to implement a static RecordSQLService, that has method save(Record r). Your app could start RecordSQLService when the app launches, so it will remain alive as long as your app does, and it takes the responsibility of saving away from the Record class, which makes it so you don't need Context anymore and can Parcel it.

Categories

Resources