Initialize List using getter setter - java

I am trying to initialize a List using setter method in same class when I will receive a response but when I called getter from other class its returning an empty list. Is it technically possible what I'm trying to achieve?
public class CategoryCommonAPI
{
private Context context;
private String endUrl;
private UserAccessToken userAccessToken;
private String ITV_BASE_URL;
private List<CategoryCommonResponse> itemq;
public CategoryCommonAPI(Context context, String endUrl, List<CategoryCommonResponse> itemq)
{
this.context = context;
this.endUrl = endUrl;
this.itemq = itemq;
ITV_BASE_URL = context.getString(R.string.baseUrl);
userAccessToken = new UserAccessToken(context);
}
public void getAllCategory()
{
Toast.makeText(context, "Iam thanos", Toast.LENGTH_SHORT).show();
String token ="Bearer "+userAccessToken.getAccessToken();
final ITV_API_Service itvApiService = RetrofitClient.getClient(ITV_BASE_URL).create(ITV_API_Service.class);
itvApiService.categoriesItem(endUrl,token).enqueue(new Callback<List<CategoryCommonResponse>>() {
#Override
public void onResponse(Call<List<CategoryCommonResponse>> call, Response<List<CategoryCommonResponse>> response)
{
if (response.isSuccessful())
{
List<CategoryCommonResponse> item = response.body();
Toast.makeText(context, "Iam called", Toast.LENGTH_SHORT).show();
setItem(item);
}
}
#Override
public void onFailure(Call<List<CategoryCommonResponse>> call, Throwable t)
{
Toast.makeText(context, "Image response failed", Toast.LENGTH_SHORT).show();
}
});
}
private void setItem(List<CategoryCommonResponse> item)
{
this.itemq= item;
Log.d("List size", "setItem: "+item.size());
Log.d("Return List", "setItem: "+itemq.size());
}
public List<CategoryCommonResponse> getItemq()
{
return this.itemq;
}
}
and where I'm calling it is
CategoryCommonAPI commonAPI = new CategoryCommonAPI(this, endUrl, list);
commonAPI.getAllCategory();
list=commonAPI.getItemq();
When I checked the list.size() using toast or Log.d it show 0 item.

Since its an asynchronous call and you are trying to retrieve the list immediately after it then one possible way is to return the list after setting from the getAllCategory() method itself.

Related

How can ViewModel react to its own livedata field changes?

public class WeatherDataViewModel extends ViewModel {
private MutableLiveData<String> cityName = new MutableLiveData<>();
private MutableLiveData<WeatherData> weatherData = new MutableLiveData<>();
private final WeatherDataService service = new retrofit2.Retrofit.Builder()
.baseUrl("https://api.openweathermap.org")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(WeatherDataService.class);
public LiveData<String> getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName.setValue(cityName);
}
// i want to send request everytime cityName ( live data field ) is being changed and inside this function
// i want to update weatherData ( another live data field)
public void updateWeatherData(String cityName, MutableLiveData<WeatherData> weatherData) {
service.getWeatherData(cityName).enqueue(new Callback<WeatherData>() {
#Override
public void onResponse(Call<WeatherData> call, Response<WeatherData> response) {
Log.i("RETROFIT", response.toString());
weatherData.setValue(response.body());
}
#Override
public void onFailure(Call<WeatherData> call, Throwable t) {
Log.e("RETROFIT", t.getMessage());
Log.e("RETROFIT", "Nie udało się pobrać poprawnie danych z API");
}
});
}
}
I want to send request everytime cityName ( live data field ) is being changed and inside this function updateWeatherData method I want to update weatherData ( another live data field)
Can someone help?

how to store json array response using retrofit

I want to call an api endpoint and display the associated response in my android app.
The api takes a parameter user_name and return response of that user.
Response is in json array consisting json of date, location and img (base64).
RESPONSE
[
{
"id": "602a1901a54781517ecb717c",
"date": "2021-02-15T06:47:29.191000",
"location": "mall",
"img": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAMEBgUGBgYFBgYGBwkIBgcJBwYGCAsICQoKCgoKBggLDAsKDAkKCgr/2wBDAQICAgICAgUDAwUKBwYHCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgr/wAARCASvBLADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/
}
]
the issue I am facing is I am not able to store the response and parse it.
I am using retrofit for this.
There is no issue in the api call the server gets a successfull request the issue is in the client side (android app).
Here is the code that i currently have.
ApiInterface.java
interface ApiInterface {
#FormUrlEncoded
#POST("end_point")
Call<List<Task>>getstatus(#Field("user_name") String user_name);
}
Task.java
public class Task {
#SerializedName("user_name")
public String user_name;
public Task(String user_name) {
user_name = user_name.substring(1, user_name.length()-1);
this.user_name= user_name;
}
public String getUser() {
return user_name;
}
}
MainActivity.java
private void LoginRetrofit(String user_name) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("url")
.addConverterFactory(GsonConverterFactory.create())
.build();
final ApiInterface request = retrofit.create(ApiInterface.class);
Call<List<Task>> call = request.getstatus(user_name);
Toast.makeText(getApplicationContext(), "user_name" + " " + call.request(), Toast.LENGTH_LONG).show();
call.enqueue(new Callback<List<Task>>() {
#Override
public void onResponse(Call<List<Task>> call, Response<List<Task>> response) {
try {
List<Task> rs=response.body();
Toast.makeText(getApplicationContext(), "Response" + " "+rs, Toast.LENGTH_LONG).show();
}
catch (Exception e)
{
Log.d("REsponse error",e.getMessage());
}
}
#Override
public void onFailure(Call<List<Task>> call, Throwable t) {
Log.d("Error",t.getMessage());
}
});
}
This is the response which is being returned.
In MainActivity.java file, update the code as below as you are printing rs object in your toast message, it prints only the object address not the value in it. So to print the value of the object you received, you must call the methods of the object to get value like as.
MainActivity.java
private void LoginRetrofit(String user_name) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("url")
.addConverterFactory(GsonConverterFactory.create())
.build();
...
call.enqueue(new Callback<List<Task>>() {
#Override
public void onResponse(Call<List<Task>> call, Response<List<Task>> response) {
try {
List<Task> rs=response.body();
if(rs.size() > 0){
Task user = rs.get(0);
String id = user.getId();
String location = user.getLocation();
Toast.makeText(getApplicationContext(),"Response : Id="+id+" and location="+location, Toast.LENGTH_LONG).show();
}
}
catch (Exception e)
{
Log.d("REsponse error",e.getMessage());
}
}
...
});
}
and update the Task model as
Task.java
public class Task {
#SerializedName("id") public String id;
#SerializedName("date") public String date;
#SerializedName("location") public String location;
#SerializedName("img") public String img;
public Task(String id, String date, String location, String img) {
this.id=id;
this.date=date;
this.location=location;
this.img=img;
}
public String getId(){ return this.id; }
public String getDate(){ return this.date; }
public String getLocation(){ return this.location; }
public String getImg(){ return this.img; }
}
Your data model class variables should be serialized or to have names as same as in the response , so that retrofit can be able to bind response values to your model variables .
Also you must have a variable in your model class for each key-value pair in your response that you want to use .
check this example to get how retrofit really work .

How to create dynamically class in Android

In my application, I should use Material Stepper and for this, I want to use this library : https://github.com/ernestoyaquello/VerticalStepperForm
But I want to add this dynamically from server.
For connecting with server I used Retrofit library and I should check the type of items from server.
when this type is "penny" show one of this steps and when the type is "best" show another step.
I create this steps from library tutorials, but i want when type is penny show me StepDynamicTxt and when the type is best show me StepDynamicEdt!
I write below codes but just add one of the items from each step!
But in API, I have 2 item of penny types and 3 items of best type!
Should show me 5 step, but show me 2 step!
My codes :
public class StepperActivity extends AppCompatActivity {
private ApiServices apiServices;
private ProgressBar loader;
private VerticalStepperFormView stepper;
private StepDynamicEdt stepDynamicEdt;
private StepDynamicTxt stepDynamicTxt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bidzila_stepper);
//Initialize
apiServices = ApiClient.ApiClient().create(ApiServices.class);
loader = findViewById(R.id.bidStepper_loader);
stepper = findViewById(R.id.bidStepper);
//Api
callAPi();
}
private void callAPi() {
loader.setVisibility(View.VISIBLE);
Call<TodayResponse> call = apiServices.TODAY_RESPONSE_CALL(5);
call.enqueue(new Callback<TodayResponse>() {
#Override
public void onResponse(Call<TodayResponse> call, Response<TodayResponse> response) {
if (response.isSuccessful()) {
if (response.body() != null) {
if (response.body().getRes() != null) {
if (response.body().getRes().getToday().size() > 0) {
loader.setVisibility(View.GONE);
//Foreach
for (int i = 0; i < response.body().getRes().getToday().size(); i++) {
if (response.body().getRes().getToday().get(i).getType().equals("penny")) {
stepDynamicEdt = new StepDynamicEdt(response.body().getRes().getToday().get(i).getName());
} else if (response.body().getRes().getToday().get(i).getType().equals("best")) {
stepDynamicTxt = new StepDynamicTxt(response.body().getRes().getToday().get(i).getName());
}
}
stepper.setup(new StepperFormListener() {
#Override
public void onCompletedForm() {
}
#Override
public void onCancelledForm() {
}
}, stepDynamicEdt, stepDynamicTxt)
.allowNonLinearNavigation(false)
.displayCancelButtonInLastStep(false)
.displayBottomNavigation(false)
.confirmationStepTitle("Confirm")
.stepNextButtonText("Continue")
.lastStepNextButtonText("Finish")
.includeConfirmationStep(false)
.init();
}
}
}
}
}
#Override
public void onFailure(Call<TodayResponse> call, Throwable t) {
Log.e("ResponseErr", t.getMessage());
}
});
}
#Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase));
}
}
I think this problem for this line:}, stepDynamicEdt, stepDynamicTxt) because just add 2 step.
How can i add this step dynamically in Android?
In your code, you are making a very fundamental mistake. And that is, you are using the same variable each time in your loop to store dynamic edit type and dynamic text type, which will replace any previously created fields. And hence when you finally create them, you end up with single last values of each type.
What you can do is, create a List with type Step, add new type every time you get them, and finally pass that list to the builder.
The builder accepts a list too, you should check implementation when its open source.
// before the for loop, create a list of type Step
List<Step> steps = new ArrayList();
// your loop on response received from server
for (int i = 0; i < response.body().getRes().getToday().size(); i++) {
if (response.body().getRes().getToday().get(i).getType().equals("penny")) {
StepDynamicEdt stepDynamicEdt = new StepDynamicEdt(response.body().getRes().getToday().get(i).getName());
// add to list
steps.add(stepDynamicEdt);
} else if (response.body().getRes().getToday().get(i).getType().equals("best")) {
StepDynamicTxt stepDynamicTxt = new StepDynamicTxt(response.body().getRes().getToday().get(i).getName());
// add to list
steps.add(stepDynamicTxt);
}
}
// finally create them
stepper.setup(new StepperFormListener() {
#Override
public void onCompletedForm() {
}
#Override
public void onCancelledForm() {
}
}, steps) // pass the list
.allowNonLinearNavigation(false)
.displayCancelButtonInLastStep(false)
.displayBottomNavigation(false)
.confirmationStepTitle("Confirm")
.stepNextButtonText("Continue")
.lastStepNextButtonText("Finish")
.includeConfirmationStep(false)
.init();

2 Key Questions in Firebase

I am using Firebase.
1. Question:
I create a Key with:
final String CHATS_CHILD = "chats/" + mFirebaseDatabaseReference.push().getKey();
mFirebaseDatabaseReference.child(CHATS_CHILD).push().setValue("and so on...");
The result you see in the picture. Now I created a key with childrens in Firebase but how to I get the key into my android app? (I mean the first key, after Chats)
2. Qestion is similar
You see the databe in my Picture. How can I get the first key after chats, when I search after the text? So for example I want the key which has as child the Text "Test1"
How to do that?
Thanks in advance.
I think you should flatten your data in order to get message key and chat key using just message text. You can keep actual messages in a separate path (like "messages") and keep only message keys inside related chat's path, as shown in the following structure:
Create Chat class:
public class Chat {
private Map<String, Boolean> messageKeys;
public Chat() {
// Default constructor required for calls to DataSnapshot.getValue(Chat.class)
}
public Chat(Map<String, Boolean> messageKeys) {
this.messageKeys = messageKeys;
}
public Map<String, Boolean> getMessageKeys() {
return messageKeys;
}
public void setMessageKeys(Map<String, Boolean> messageKeys) {
this.messageKeys = messageKeys;
}
}
..and Message class:
public class Message {
private String chatKey;
private String text;
private long time;
public Message() {
// Default constructor required for calls to DataSnapshot.getValue(Message.class)
}
public Message(String chatKey, String text, long time) {
this.chatKey = chatKey;
this.text = text;
this.time = time;
}
public String getChatKey() {
return chatKey;
}
public void setChatKey(String chatKey) {
this.chatKey = chatKey;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
}
Then query messages and find those whose text field is equal to the term you are searching, for example "Test1":
DatabaseReference chatsRef = FirebaseDatabase.getInstance().getReference("chats");
DatabaseReference messagesRef = FirebaseDatabase.getInstance().getReference("messages");
messagesRef.orderByChild("text").equalTo("Test1").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren()) {
String messageKey = child.getKey();
Message message = child.getValue(Message.class);
String chatKey = message.getChatKey();
// Now you have both the chatKey and the messageKey...
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
Creating a new chat and its first message would look like below in this case (can be considered as answer to your first question):
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
String chatKey = rootRef.push().getKey();
String messageKey = rootRef.push().getKey();
Message newMessage = new Message(chatKey, "My message trial", Calendar.getInstance().getTimeInMillis());
Map<String, Boolean> messageKeys = new LinkedHashMap<>();
messageKeys.put(messageKey, true);
Chat newChat = new Chat(messageKeys);
rootRef.child("messages").child(messageKey).setValue(newMessage);
rootRef.child("chats").child(chatKey).setValue(newChat);
Retrieving all messages that belongs to a chat whose key is known:
String chatKey = "chatKey1"; // Get it somehow
DatabaseReference messagesRef = FirebaseDatabase.getInstance().getReference("messages");
messagesRef.orderByChild("chatKey").equalTo(chatKey).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<Message> messageList = new ArrayList<>();
for (DataSnapshot child : dataSnapshot.getChildren()) {
String messageKey = child.getKey();
Message message = child.getValue(Message.class);
messageList.add(message);
}
// Now you have all messages in messageList...
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
in additional to answer of Mehmed: Firebase DB supports not only setting/retrieving single fields, but also whole the objects of some class.
In the example below I define class MyChat, create few objects of it and put them into Firebase DB. Then I retrieve all of them (as objects, not just strings) and put them into ArrayList.
FirebaseDatabase frDb = FirebaseDatabase.getInstance();
DatabaseReference mFirebaseDatabaseReference = frDb.getReference();
final String CHATS_CHILD = "chats/theChat" ; //+ mFirebaseDatabaseReference.push().getKey();
// Create 3 objects of class MyChat
MyChat chat1 = new MyChat("Test1", "21-Sep-2017");
MyChat chat2 = new MyChat("Test21", "26-Sep-2017");
MyChat chat3 = new MyChat("TestB", "28-Sep-2010");
//Add all the chats to Firebase DB
mFirebaseDatabaseReference.child(CHATS_CHILD).push().setValue(chat1);
mFirebaseDatabaseReference.child(CHATS_CHILD).push().setValue(chat2);
mFirebaseDatabaseReference.child(CHATS_CHILD).push().setValue(chat3);
// Here we will retrieve all the chats and put them to array
// Declare array to keep results
final ArrayList<MyChat> arr1 = new ArrayList<MyChat>();
//Listener
ChildEventListener chEvLst = mFirebaseDatabaseReference.child("chats").addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
for (DataSnapshot ds1 : dataSnapshot.getChildren()) {
MyChat chatRes = ds1.getValue(MyChat.class);
Log.i("Next chat text:",chatRes.getmText());
Log.i("Next chat date:",chatRes.getmText());
arr1.add(chatRes); // retrieve and save chats to array
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
And this is class MyChat
public class MyChat {
String mText = "Test1"; // default values...
String mDate = "26-Sep-2017";
// *** MUST TO HAVE EMPTY CONSTUCTOR FOR FIREBASE !!! ***
public MyChat() {
}
// Second constructor
public MyChat(String mText, String mDate) {
this.mText = mText;
this.mDate = mDate;
}
// *** MUST TO HAVE ALL GETTERS/SETTERS FOR FIREBASE!!! ***
// Getters/setters
public String getmText() {
return mText;
}
public void setmText(String mText) {
this.mText = mText;
}
public String getmDate() {
return mDate;
}
public void setmDate(String mDate) {
this.mDate = mDate;
}
}
And this is resulting DB structure :
Best regards!

How to solve 404 on Retrofit #POST on Django RESTful API?

I am able to get data from database using retrofit and REST api but facing errors in Posting data. Post works using postman but not through retrofit.I have been unable to locate the error.I have tried changing endpoint, that is, "rest" and "rest/" but still get not found error.
ApiView of Post in Django RESTful api: view.py
def post(self,request):
serializer =table_restSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response({'results':serializer.data},status=201)
return Response(serializer.errors, status=404)
urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^rest',views.restSerializer.as_view())
]
urlpatterns = format_suffix_patterns(urlpatterns)
serializer.py:
class table_restSerializer(serializers.ModelSerializer):
class Meta:
model = table_rest
fields = '__all__'
My android code:
Interface
public interface ApiInterface {
#GET("rest")
Call<CustomViewResponse> getJsonFromSid();
#POST("rest")
Call<CustomViewResponse> createTask(#Body CustomViewHolder task);
}
CustomViewHolder class:
public class CustomViewHolder {
#SerializedName("id")
private Integer id;
#SerializedName("tt")
private String tt;
#SerializedName("varr")
private Integer varr;
#SerializedName("edi")
private String edi;
public CustomViewHolder(String tt, Integer varr, String edi){
this.tt = tt;
this.varr = varr;
this.edi = edi;
}
public Integer getid(){
return id;
}
/*public void setid(Integer id){
this.id = id;
}*/
public String gettt()
{
return tt;
}
public void settt(String tt){
this.tt = tt;
}
public Integer getvarr(){
return varr;
}
public void setvarr(Integer varr){
this.varr = varr;
}
public String getedi(){
return edi;
}
public void setedi(String edi){
this.edi = edi;
}
}
CustomViewResponse class
public class CustomViewResponse {
#SerializedName("results")
private List<CustomViewHolder> results;
public List<CustomViewHolder> getResults(){
return results;
}
}
MainActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.sid_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
ApiInterface apiService1 = ApiClient.getClient().create(ApiInterface.class);
Call<CustomViewResponse> call = apiService.getJsonFromSid();
CustomViewHolder cc = new CustomViewHolder("my task title",22,"a string");
call.enqueue(new Callback<CustomViewResponse>() {
#Override
public void onResponse(Call<CustomViewResponse> call, Response<CustomViewResponse> response) {
int statuscode = response.code();
List<CustomViewHolder> customViewHolders = response.body().getResults();
recyclerView.setAdapter(new AdapterSid(customViewHolders, R.layout.list_item_sid, getApplicationContext()));
}
#Override
public void onFailure(Call<CustomViewResponse> call, Throwable t) {
Log.e("TAG main", t.toString());
}
});
call1.enqueue(new Callback<CustomViewResponse>() {
#Override
public void onResponse(Call<CustomViewResponse> call1, Response<CustomViewResponse> respo) {
int statuscode = respo.code();
Log.d("Message", "code..."+respo.code() + " message..." + respo.message());
CustomViewResponse respon = respo.body();
if (respon == null){
Log.e("Error",""+statuscode+ "......"+ respo.message()+"....null body");
}
}
#Override
public void onFailure(Call<CustomViewResponse> call1, Throwable t) {
Log.e(TAG, t.toString());
}
});
}
Following is my table structure:
class table_rest(models.Model):
tt = models.CharField(max_length=10,default = 12)
varr = models.IntegerField(default=30)
edi = models.CharField(max_length=1000,default='44')
def __str__(self):
return self.tt
Using postman my Json body which gets successfully saved is :
{
"tt": "hello",
"varr": 911,
"edi": "emergency. Can't find solution"
}
Please add an extra URL.
urlpatterns = [
url(r'^admin/', admin.site.urls), # Any URL starting with admin(ex: http://testdomainname.com/admin/xyz)
url(r'^rest/$',views.restSerializer.as_view()), # Any URL starting with only rest(ex: http://testdomainname.com/rest/)
url(r'^$',views.restSerializer.as_view()), # Any empty URL with '' (ex: http://testdomainname.com/)
]
First I included the url pattern as suggested by Dinesh Mandepudi. Then I made changes to my regex in retrofit. It was url issue that I was not confronting when using postman. I just added '/' at the beginning of my post regex.
public interface ApiInterface {
#GET("/rest")
Call<CustomViewResponse> getJsonFromSid();
#POST("/rest/")
Call<CustomViewResponse> createTask(#Body CustomViewHolder task);
}
Also a silly mistake is I was trying to add a string of 13 length in the database column while I had set the limit to 10.

Categories

Resources