Reputation: 60
I'm trying to create the buttons using my api. I make a call to the api using the Retrofit
and then I create the buttons. But there is a code error! The data returned in the API response is correct but creating the views is a problem.
It says that I need to removeView()
. I did that but there is no data printing now.
My code:
package com.example.englishapp;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class LessonsActivity extends AppCompatActivity {
private TextView textViewResult;
String URL = "http://kurchanovenglish.ru/data/";
private String[] name = new String[18];
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lessons);
final LinearLayout layout = new LinearLayout(this);
final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
);
params.setMargins(250, 10, 250, 50);
layout.setOrientation(LinearLayout.VERTICAL);
int i;
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
JsonPlaceHolderApi jsonPlaceHolderApi = retrofit.create(JsonPlaceHolderApi.class);
Call<List<Lesson>> call = jsonPlaceHolderApi.getPosts();
final LinearLayout row = new LinearLayout(this);
final Button button = new Button(this);
call.enqueue(new Callback<List<Lesson>>() {
@Override
public void onResponse(Call<List<Lesson>> call, Response<List<Lesson>> response) {
if (!response.isSuccessful()) {
textViewResult.setText("Code: " + response.code());
return;
}
List<Lesson> lessons = response.body();
int b = 0;
String[] name = new String[18];
for (Lesson lesson : lessons) {
button.setText(lesson.getName());
button.setId(lesson.getNumber());
button.setLayoutParams(params);
button.setTextSize(20);
/*button.setBackground(this.getResources().getDrawable(R.drawable.buttons));*/
button.setOnClickListener(new View.OnClickListener() {
@SuppressLint("ShowToast")
@Override
public void onClick(View v) {
Intent intent = new Intent(LessonsActivity.this, WelcomeActivity.class);
startActivity(intent);
}
});
row.removeView(layout);
row.addView(button);
}
layout.addView(row);
}
@Override
public void onFailure(Call<List<Lesson>> call, Throwable t) {
textViewResult.setText(t.getMessage());
}
});
}
}
The error:
/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.englishapp, PID: 19385
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:4915)
at android.view.ViewGroup.addView(ViewGroup.java:4746)
at android.view.ViewGroup.addView(ViewGroup.java:4686)
at android.view.ViewGroup.addView(ViewGroup.java:4659)
at com.example.englishapp.LessonsActivity$1.onResponse(LessonsActivity.java:92)
at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1$1.run(DefaultCallAdapterFactory.java:83)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Help me please. I don't know what to do.
Upvotes: 1
Views: 205
Reputation: 3331
Here is what you're doing wrong; You are using the same Button
instance and adding it again to row
(LinearLayout
).
If I understand correctly this is the view hierarchy you want.
LinearLayout
--LinearLayout
--Button
--Button
.
--LinearLayout
--Button
--Button
.
.
First thing you need to understand is that you cannot reuse a View
in multiple places in the view hierarchy. Secondly a View
cannot be a child to multiple parents i.e. a same Button
cannot be present in two rows. Lets think about the reason for such restriction; say, you were allowed to add same Button
to another parent, how would you then identify a click among them, how would you know which one you clicked. Furthermore say you have a text to display on one and a different one for the second Button
, how would you change for each if/when you are sharing the reference. You see the problem?
However, since you are instantiating and adding the Button
in Java code. You need to first create a new instance of Button
to add to the parent row
. Consequently you also need a new instance of row to add to the parent layout
if you are adding more than one rows.
Your code then becomes:
for (Lesson lesson : lessons) {
Button button = new Button(LessonsActivity.this);
button.setText(lesson.getName());
button.setId(lesson.getNumber());
button.setLayoutParams(params);
button.setTextSize(20);
/*button.setBackground(this.getResources().getDrawable(R.drawable.buttons));*/
button.setOnClickListener(new View.OnClickListener() {
@SuppressLint("ShowToast")
@Override
public void onClick(View v) {
Intent intent = new Intent(LessonsActivity.this, WelcomeActivity.class);
startActivity(intent);
}
});
row.addView(button);
}
layout.addView(row);
}
You will need to adjust layout.addView(row);
accordingly but same principle follows.
Upvotes: 1