Create class structure like glide and picasso in android - java

I want to create class structure like:
Glide.with(context).load("url").into(imageView);
Problem :-
public class Slider{
private static Activity context;
private static int Duration = 3000;
public static void setContext(Activity context) {
Slider.context = context;
}
public static void setDuration(Duration duration) {
Slider.Duration = duration;
}
}
// In Activity
Slider.setContext(this);
I declared all methods and required fields static but it can't work.
I tried with setter method but it allows only one setter.This class doesn't allow me to use second setter.
Requirement :
Slider.setContext(this).setDuration(3000);
I need class and method structure like glide and picasso library and some methods are compulsory.

You need to use Builder Pattern for this
public class Slider
{
private static Activity context;
private static int Duration = 3000;
private Slider(SliderBuilder builder) {
this.context = builder.context;
this.Duration = builder.Duration;
}
//All getter, and NO setter to provde immutability
public String getContext() {
return context;
}
public String getDuration() {
return Duration;
}
public static SliderBuilder with(Activity context){
return new SliderBuilder(context);
}
public static class SliderBuilder
{
private static Activity context;
private static int Duration = 3000;
public SliderBuilder(Activity context) {
this.context = context;
}
public SliderBuilder duration(int Duration) {
this.Duration = Duration;
return this;
}
//Return the finally constructed Slider object
public Slider build() {
Slider slider = new Slider(this);
validateSliderObject(slider);
return slider;
}
private void validateSliderObject(Slider slider) {
//Do some basic validations to check
}
}
}
Better explained here
EDIT
How to use
Slider.with(this).duration(3000).build();

Related

Simplify multiple inheriting classes (with all same content) of abstract class

I like to count multiple things in my app and save the value to android sharedpreferences. Everything works, but I am not satisfied with the class design in general.
Very simple abstract class. Class parameter is used to name keys in sharedPreferences.
public abstract class Counter {
private Context mContext;
private Class mClass;
Counter(Class myClass, Context context) {
this.mClass = myClass;
this.mContext = context;
}
public Integer getValue() {
return PrefManager.with(mContext).getInt(mClass.getName(), 0);
//return UniversalPreferences.getInstance().get(counterName, 1);
}
public void increment() {
PrefManager.with(mContext).save(mClass.getName(), getValue() + 1);
//UniversalPreferences.getInstance().put(counterName, getCurrentValue(counterName) + 1);
}
}
So far I have already 5 classes inheriting from Counter with all the same content.
public class CounterAppLaunch extends Counter {
#SuppressLint("StaticFieldLeak")
private static CounterAppLaunch instance;
private CounterAppLaunch(Context context) {
super(CounterAppLaunch.class, context);
}
public static CounterAppLaunch getInstance(Context context) {
if(CounterAppLaunch.instance == null) {
CounterAppLaunch.instance = new CounterAppLaunch(context);
}
return CounterAppLaunch.instance;
}
}
I have counters I like to call from different classes and increment there (eg. CounterAPICall or CounterOnResumeCallExample). Which works with this code just fine.
This code might be useful to retrieve an appropriate counter:
public Counter{
private int count;
public Counter(){
count = 0;
}
public int getValue(){
return count;
}
public void increment(){
counter++;
}
}
public CounterStorage(){
private static HashMap<String, Counter> counterMap = new HashMap<>();
public static Counter getInstance(String str){
if (counterMap.containsKey(str)) return counterMap.get(str);
Counter newCounter = new Counter();
counterMap.add(str, newCounter);
return newCounter;
}
}
In this case, Counter isn't an abstract class. For any purpose, you can give a Counter a name, which is stored in the map.
With the help of Dependency injection and having HasA also, we can try,
public class CounterAppLaunch{
#Autowired
CounterAdapter counterAdapter;
#SuppressLint("StaticFieldLeak")
private static CounterAppLaunch instance;
private CounterAppLaunch(Context context) {
super(CounterAppLaunch.class, context);
}
public static CounterAppLaunch getInstance(Context context) {
if(CounterAppLaunch.instance == null) {
CounterAppLaunch.instance = new CounterAppLaunch(context);
}
return CounterAppLaunch.instance;
}
}
CounterAdapter extends Counter{
#Autowired
private Context mContext;
#Autowired
private Class mClass;
// getter and setter
}
public abstract class Counter {
private Context mContext;
private Class mClass;
Counter(Class myClass, Context context) {
this.mClass = myClass;
this.mContext = context;
}
public Integer getValue() {
return PrefManager.with(mContext).getInt(mClass.getName(), 0);
//return UniversalPreferences.getInstance().get(counterName, 1);
}
public void increment() {
PrefManager.with(mContext).save(mClass.getName(), getValue() + 1);
//UniversalPreferences.getInstance().put(counterName, getCurrentValue(counterName) + 1);
}
}

save arrayList<Class> as a string inside Room

I am using Room library from jetpack and i want to save my arrayList inside Room database.
I am using typeConverter to convert arrayList into String, but still getting error.
Error Message : Cannot figure out how to save this field into database. You can consider adding a type converter for it.
this is my typeConverter.
public class TypeConverterUtils {
#TypeConverter
public static String fromArray(ArrayList<CropData> arrayList) {
return GsonUtils.toGson(arrayList);
}
}
this is my Database class.
#TypeConverters({TypeConverterUtils.class})
public abstract class CheruvuDatabase extends RoomDatabase {
private static final String DATABASE_NAME = "Cheruvu.db";
public abstract OtpDAO otpDAO();
public abstract FarmerInfoDAO farmerInfoDAO();
// For Singleton instantiation
private static final Object LOCK = new Object();
private static volatile CheruvuDatabase sInstance;
public static CheruvuDatabase getInstance(Context context) {
if (sInstance == null) {
synchronized (LOCK) {
if (sInstance == null) {
context.getApplicationContext().deleteDatabase(CheruvuDatabase.DATABASE_NAME);
sInstance = Room.databaseBuilder(context.getApplicationContext(), CheruvuDatabase.class, CheruvuDatabase.DATABASE_NAME)
.fallbackToDestructiveMigration()
.allowMainThreadQueries()
.build();
}
}
}
return sInstance;
}
}
I want to store this ArrayList.
private ArrayList cropData = new ArrayList<>();
this is my CropData class.
public class CropData {
private String cropName;
private Crop crop;
private Float cropAcres;
private Float cropYield;
private Float cropPrice;
public String getCropName() {
return cropName;
}
public void setCropName(String cropName) {
this.cropName = cropName;
}
public Crop getCrop() {
return crop;
}
public void setCrop(Crop crop) {
this.crop = crop;
}
public Float getCropAcres() {
return cropAcres;
}
public void setCropAcres(Float cropAcres) {
this.cropAcres = cropAcres;
}
public Float getCropYield() {
return cropYield;
}
public void setCropYield(Float cropYield) {
this.cropYield = cropYield;
}
public Float getCropPrice() {
return cropPrice;
}
public void setCropPrice(Float cropPrice) {
this.cropPrice = cropPrice;
}
}
Have you added #Embedded on the ArrayList variable? because you will be needed to Embed the Class, that you want to convert.
for example,
ArrayList<CropData> cropData;
and CropData.class is different. so just add
#Embedded
ArrayList<CropData> cropData;
and your problem will be solved.

Using AsyncTask in Activity fails

I have an application in which I wanted to store a list of items and I figured a database would do. I found out about the new Room API and tried using it, though I'm having some trouble getting it working. I have a background service which is supposed to write entries to the database. I read that using the singleton pattern was recomended, but I can't seem to get it working. When I try to retrieve all entries in my MainActivity, the list I get back is always empty, indicating that I wasn't able to save them from the start.
Singleton db class
#Database(entities = {TemperatureReading.class}, version = 1)
public abstract class DatabaseSingleton extends RoomDatabase {
private static DatabaseSingleton INSTANCE;
public abstract TemperatureReadingDao temperatureReadingDao();
public static DatabaseSingleton getAppDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE =
Room.databaseBuilder(context.getApplicationContext(), DatabaseSingleton.class, "fireTempDatabase")
.build();
}
return INSTANCE;
}
public static void destroyInstance() {
INSTANCE = null;
}
}
Entity
#Entity
public class TemperatureReading {
#PrimaryKey(autoGenerate = true)
private int uid;
#ColumnInfo(name = "dateTime")
private long dateTime;
#ColumnInfo(name = "location")
private String readingLocation;
#ColumnInfo(name = "value")
private float value;
public long getDateTime() {
return dateTime;
}
public void setDateTime(long dateTime) {
this.dateTime = dateTime;
}
public String getReadingLocation() {
return readingLocation;
}
public void setReadingLocation(String readingLocation) {
this.readingLocation = readingLocation;
}
public float getValue() {
return value;
}
public void setValue(float value) {
this.value = value;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
}
EntityDAO
#Dao
public interface TemperatureReadingDao {
#Query("SELECT * FROM temperatureReading")
List<TemperatureReading> getAll();
#Query("SELECT * FROM temperatureReading ORDER BY uid desc limit 1")
TemperatureReading getLatest();
#Insert
void insertAll(TemperatureReading... temperatureReading);
#Update
void update(TemperatureReading... temperatureReading);
#Delete
void delete(TemperatureReading temperatureReading);
}
Background service which saves to db
private void saveTempDatabase(float tmpMessageAsFloat, long tmpMessageDateTime) {
Log.d(TAG, "saveTempDatabase");
TemperatureReading tr = new TemperatureReading();
tr.setDateTime(tmpMessageDateTime);
tr.setReadingLocation("XXX"); //TODO
tr.setValue(tmpMessageAsFloat);
DatabaseSingleton.getAppDatabase(getApplicationContext()).temperatureReadingDao().insertAll(tr);
}
MainActivity were db is read from, uses Async task so it doesn't block UI
private void updateTemperature() {
Log.d(TAG, "updateTemperature");
new AsyncTask<Void, Void, Integer>() {
#Override
protected Integer doInBackground(Void... params) {
List<TemperatureReading> tr = DatabaseSingleton.getAppDatabase(MainActivity.this).temperatureReadingDao().getAll(); //List is always empty, no matter how many times I have called the saveTempDatabase() method in the service class.
return 0;
}
#Override
protected void onPostExecute(Integer agentsCount) {
}
}.execute();
}
Maybe it has to do with the context somehow?
EDIT:
Just tried adding .allowMainThreadQueries() when building the database and now it works. So for some reason my Async task isn't working?
Your AsyncTask seems to be wrong. You should return the list you would like to handle in doInBackground and then expect it in onPostExecute. Why do you always return 0?

How to build chain of responsibility using constructor for initializing next chains?

How to build a chain of responsibility using constructor for initializing chains.
Here is my Runner.class where i'm building my chain using setNext method.
public class Runner {
private static final String ENTER_PATH = "Enter path: ";
private static final String FILTER_BY_NAME = "Filter by name? (0/1)";
private static final String ENTER_NAME_PARAMETER = "Enter name parameter please: ";
private static final String FILTER_BY_EXTENSION = "Filter by extension? (0/1)";
private static final String ENTER_EXTENSION_PARAMETER = "Enter extension please (without '.'): ";
private static final String FILTER_BY_SIZE = "Filter by size? (0/1)";
private static final String ENTER_SIZE_TO = "Enter upper limit searching files in kb";
private static final String ENTER_SIZE_FROM = "Enter lower limit searching files in kb";
private static final String TRUE="1";
private Scanner scanner;
private List<File> fileList;
public Runner() {
this.scanner = new Scanner(System.in);
this.fileList = new ArrayList<>();
}
private String getDirName(){
System.out.println(ENTER_PATH);
return scanner.nextLine();
}
private Handler getChainOfResponsibility(){
GeneralHandler generalHandler = new GeneralHandler();
Handler lastHandler = generalHandler;
System.out.println(FILTER_BY_NAME);
if (scanner.nextLine().equals(TRUE)) {
System.out.println(ENTER_NAME_PARAMETER);
String name = scanner.nextLine();
Handler nameHandler = new NameHandler(name);
lastHandler.setHandler(nameHandler);
lastHandler = nameHandler;
}
System.out.println(FILTER_BY_EXTENSION);
if (scanner.nextLine().equals(TRUE)) {
System.out.println(ENTER_EXTENSION_PARAMETER);
Handler extensionHandler = new ExtensionHandler(scanner.nextLine());
lastHandler.setHandler(extensionHandler);
lastHandler = extensionHandler;
}
System.out.println(FILTER_BY_SIZE);
if (scanner.nextLine().equals(TRUE)) {
System.out.println(ENTER_SIZE_FROM);
double fromSize = scanner.nextDouble();
System.out.println(ENTER_SIZE_TO);
double toSize = scanner.nextDouble();
Handler sizeHandler = new SizeHandler(fromSize, toSize);
lastHandler.setHandler(sizeHandler);
}
return generalHandler;
}
public void run() throws InterruptedException, IOException {
findAllFiles(getDirName(), getChainOfResponsibility());
showListOfFilteredFiles();
}
Here is my Handler abstract class
public abstract class Handler {
private Handler handler;
public void setHandler(Handler handler) {
this.handler = handler;
}
protected abstract boolean handleFilter(File file);
public boolean doFilter(File file){
if(handleFilter(file)){
if(Objects.nonNull(handler)){
return handler.doFilter(file);
}
return true;
}
return false;
}
}
And also i have it's implementation. How to make, that it will be init through constructor! Help pls!
Preamble
Your implementation is wrong; the general way of implementing the Chain of Responsibility pattern is for each link in the chain to forward the request to the next link if it cannot handle the request itself. This is traditionally done by delegating to the abstract super class if the current class cannot handle the request. So in short, to comply with tradition, I would rewrite your Handler class as follows:
public abstract class Handler {
private Handler next;
public void setHandler(Handler next) {
this.next = next;
}
public boolean doFilter(File file) {
return next.doFilter(file);
}
}
I have not read the contract of either your Handler nor NameHandler classes, but I'll just make a few assumptions in order to provide an example of how the NameHandler might look like after refactoring its parent:
public class NameHandler extends Handler {
private final String name;
public NameHandler(String name){
this.name = name;
}
#Override
public boolean doFilter(File file){
final boolean result;
if(file.getName().equals(name)){
result = true;
}else{
result = super.doFilter(file);
}
return result;
}
}
Answer
Use constructors to configure the next link in the chain as opposed to "setters" like your setHandler method:
public abstract class Handler {
private final Handler next;
public Handler(Handler next){
this.next = next;
}
public boolean doFilter(File file){
return next.doFilter(file);
}
}
Now your subclasses are required to deal with the non-default constructor:
public class NameHandler extends Handler {
private final String name;
public NameHandler(String name, Handler next){
super(next);
this.name = name;
}
#Override
public boolean doFilter(File file){
final boolean result;
if(file.getName().equals(name)){
result = true;
}else{
result = super.doFilter(file);
}
return result;
}
}

putParcelableArrayListExtra and black screen

I have custom class that implements Parcelable and I use it as custom arraylist.
When I use putParcelableArrayListExtra and 400 rows it works fine, but 1000 rows it does not. I have black screen and app locks up. What is wrong?
EDIT:
I sent it here and I don't use it in another Activity.
Intent intent = new Intent().setClass(getApplicationContext(), ArtActivity.class);
intent.putParcelableArrayListExtra ("mylist", list);
startActivityForResult(intent, SECONDARY_ACTIVITY_REQUEST_CODE);
My array:
ArrayList<Piece> list = new ArrayList<Piece>();
It is my Class:
public class Piece implements Parcelable {
private String id;
private String name;
private int type;
private String text;
private String mp3;
public Piece (String id,String name,int type)
{
this.id=id;
this.name=name;
this.type=type;
}
public Piece(Piece ele)
{
this.id=ele.id;
this.name=ele.name;
this.type=ele.type;
this.text=ele.text;
}
public Piece (Parcel in)
{
id = in.readString ();
name = in.readString ();
type = in.readInt();
text= in.readString();
mp3=in.readString();
}
public static final Parcelable.Creator<Piece> CREATOR
= new Parcelable.Creator<Piece>()
{
public Piece createFromParcel(Parcel in)
{
return new Piece(in);
}
public Piece[] newArray (int size)
{
return new Piece[size];
}
};
public void makeText(String text)
{
this.text=text;
}
public void makeMp3(String mp3)
{
this.mp3= mp3;
}
public String getMp3()
{
return this.mp3;
}
public String getId()
{
return id;
}
public String getName()
{
return name;
}
public int getType()
{
return type;
}
public String getText()
{
return text;
}
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeString (id);
dest.writeString (name);
dest.writeInt(type);
dest.writeString (text);
dest.writeString (mp3);
}
}
I do not believe you should be using parcelable in this case. I would either access the data statically (if you only intend to have one persistent instance of the data), or use a caching system to hold onto the data.
This is an example of a publicly available static variable:
public static List<Piece> list;
It is accessible from everywhere in your app that has visibility of the class.
However, doing this is very messy and is considered a bad practice. Alternatively, you can create an object to manage the data for you as a static class or singleton:
public class MyListManager {
private static List<Piece> mList;
public static List<Piece> getMyList() {
return mList;
}
public static void setList(List<Piece> list) {
mList = list;
}
}
Alternatively, you can implement some kind of a caching system to manage your data.

Categories