Inner class issue when using onclicklistener - android

I keep getting repeated issues with: variable is accessed from within inner class
every time i want to use an object etc from an onclicklistener etc.
I know the problem is that its not set to final, but if i set to final im not able to do anything to it before pressing the onclicklistener button...
Example i have an EditText field, which is filled with getText from an object, then i want to press an apply button and the object with the new text from the textfield.
This doesnt work when the object need to be final for the "inner class" to use it.
How do i best handle this? i keep running into this bloody phenonemon...
public class EditPicture extends Activity{
private EditText text;
private Button applyBtn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UUID itemID = (UUID)getIntent().getSerializableExtra("itemUUID");
PictureItem pi = new PictureItem("","");
final ArrayList<PictureItem> tempArray = PictureTalkFragment.array;
for(int i = 0; i < tempArray.size(); i++){
if(itemID.equals(tempArray.get(i).getId())){
pi = tempArray.get(i);
tempArray.remove(i);
}
}
setContentView(R.layout.picturetalk_edit_pic);
text = (EditText)findViewById(R.id.editName);
text.setText(pi.getTitle());
applyBtn = (Button)findViewById(R.id.applyChangeBtn);
applyBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
tempArray.add(pi);
}
});
}
}

you should define tempArray variable outside of onCreate method.
public class EditPicture extends Activity{
private EditText text;
private Button applyBtn;
ArrayList<PictureItem> tempArray
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UUID itemID = (UUID)getIntent().getSerializableExtra("itemUUID");
PictureItem pi = new PictureItem("","");
tempArray = PictureTalkFragment.array;
for(int i = 0; i < tempArray.size(); i++){
if(itemID.equals(tempArray.get(i).getId())){
pi = tempArray.get(i);
tempArray.remove(i);
}
}
setContentView(R.layout.picturetalk_edit_pic);
text = (EditText)findViewById(R.id.editName);
text.setText(pi.getTitle());
applyBtn = (Button)findViewById(R.id.applyChangeBtn);
applyBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
tempArray.add(pi);
}
});
}
}

The problem is that you add th picture to a temporary array which is not accesible when you click on it. I think that you can do something like this to define the array outside the inCreate function.
public class EditPicture extends Activity{
private EditText text;
private Button applyBtn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UUID itemID = (UUID)getIntent().getSerializableExtra("itemUUID");
PictureItem pi = new PictureItem("","");
final ArrayList<PictureItem> tempArray = PictureTalkFragment.array;
for(int i = 0; i < tempArray.size(); i++){
if(itemID.equals(tempArray.get(i).getId())){
pi = tempArray.get(i);
tempArray.remove(i);
}
}
setContentView(R.layout.picturetalk_edit_pic);
text = (EditText)findViewById(R.id.editName);
text.setText(pi.getTitle());
applyBtn = (Button)findViewById(R.id.applyChangeBtn);
applyBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(PictureTalkFragment.array != null){
PictureTalkFragment.array.add(pi);
}
}
});
}
}

Related

Can't pass multi integers at the same time in intent

So I want to pass the data between the activities,so I've make that there's 3 separate integers should be send to the second activity,but i don't know why,the emulator keeps adding all of them. Basically,I making an app, at case of my course - i need to create an app that keeping score,in my case,app would keep the score,number of fouls,and number of corners during the football match. To set the data,we are clicking in special button (press score to increment score etc.) when we want to go to the second activity and see the detailed statistics we should see like 3 goals,6 fouls,and like 2 corners for team "A" during the match,but when i clicking in buttons (suppose that is 1 time for goal,2 times for fouls,and 3 times for corner the app should be like 1 goal,2 fouls,3 corner's but it keep adding all of integers,and it's like 6 goals,6 fouls,6 corners. What can be wrong?
Count activity (here program storage the value of integers)
public class CountActivity extends AppCompatActivity {
public int team_a_score;
public int team_a_foul;
public int team_a_corner;
public int team_b_score;
public int team_b_foul;
public int team_b_corner;
private Button goToDetailedStats;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_count);
goToDetailedStats = (Button) findViewById(R.id.go_to_stats);
goToDetailedStats.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openDetailedScore();
}
});
}
private void openDetailedScore() {
Intent intent = new Intent(this,DeatiledScoreActivity.class);
intent.putExtra("",team_a_score);
intent.putExtra("",team_a_foul);
intent.putExtra("",team_a_corner);
startActivity(intent);
}
public void resetScore(View view) {
team_a_score = 0;
display_a_score(team_a_score);
team_b_score = 0;
display_b_score(team_b_score);
}
private void display_a_score (int a_score){
TextView team_a_score_tv = (TextView) findViewById(R.id.team_a_score_tv);
team_a_score_tv.setText(String.valueOf(a_score));
}
private void display_b_score (int b_score){
TextView team_b_score_tv = (TextView) findViewById(R.id.team_b_score_tv);
team_b_score_tv.setText(String.valueOf(b_score));
}
public void increment_a_score(View view) {
team_a_score = team_a_score+1;
display_a_score(team_a_score);
}
public void increment_a_foul(View view) {
team_a_foul = team_a_foul+1;
}
public void increment_a_corner(View view) {
team_a_corner = team_a_corner+1;
}
public void increment_b_score(View view) {
team_b_score = team_b_score+1;
display_b_score(team_b_score);
}
public void increment_b_foul(View view) {
team_b_foul = team_b_foul+1;
}
public void increment_b_corner(View view) {
team_b_corner = team_b_corner+1;
}
}
Detailed activity have to receive data that we send as intent from Counting activity.
public class DeatiledScoreActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_deatiled_score);
int team_a_score_detail_int = 0;
int team_a_foul_detail_int = 0;
int team_a_corner_detail_int = 0;
int team_b_score_detail_int = 0;
int team_b_foul_detail_int = 0;
int team_b_corner_detail_int = 0;
Intent goal_intent = getIntent();
int goal = goal_intent.getIntExtra("", team_a_score_detail_int);
display_a_goal(goal);
Intent foul_intent = getIntent();
int foul = foul_intent.getIntExtra("", team_a_foul_detail_int);
display_a_foul(foul);
Intent corner_intent = getIntent();
int corner = corner_intent.getIntExtra("", team_a_corner_detail_int);
display_a_corner(corner);
}
public void display_a_goal(int score) {
TextView a_score = (TextView) findViewById(R.id.team_a_goal_detail);
a_score.setText(String.valueOf(score));
}
public void display_a_foul(int foul){
TextView a_foul = (TextView) findViewById(R.id.team_a_foul_detail);
a_foul.setText(String.valueOf(foul));
They cannot have the same key:
intent.putExtra("",team_a_score);
intent.putExtra("",team_a_foul);
intent.putExtra("",team_a_corner);
So in order to make it work set:
intent.putExtra("some",team_a_score);
intent.putExtra("some2",team_a_foul);
intent.putExtra("some4",team_a_corner);
Intent putExtra method accepts two arguments key - value.

Simple Program: I/Choreographer﹕ Skipped 105 frames! The application may be doing too much work on its main thread

I am beginner and I made a simple app to draw champions from the crystals (based on Marvel COC game theme :-)). I has two activity classes i.e. DrawActivity Class, has 3 buttons to Draw 1 or 5 or 10 Hero Crystals based on Random nos generated in Champ Activity. In the logcat i can see I/Choreographer﹕ Skipped 105 frames! The application may be doing too much work on its main thread. I read other posts, but cannot understand anything what I need to do to resolve it. Appreciate your help here.
Edit - I click the buttons and click back to come to drawActivity. Repeat it multiple times, thats when i get this intermittently.
public class DrawActivity extends Activity {
private TextView mChampsList;
private Button mDraw01Button;
private Button mDraw05Button;
private Button mDraw10Button;
private int noOfChamps;
public static final String TAG ="DrawChamps";
public static final String KEY_NUMOFCHAMPS ="DrawChamps_NoOfChamps";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_draw);
mChampsList = (TextView) findViewById(R.id.champs_list);
// Log.d(TAG, ChampsActivity.getChampList());
mChampsList.setText(ChampsActivity.getChampList());
mDraw01Button = (Button) findViewById(R.id.draw1_button);
mDraw05Button = (Button) findViewById(R.id.draw5_button);
mDraw10Button = (Button) findViewById(R.id.draw10_button);
mDraw01Button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
noOfChamps = 1;
startChampActivity();
}
});
mDraw05Button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
noOfChamps = 5;
startChampActivity();
}
});
mDraw10Button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
noOfChamps = 10;
startChampActivity();
}
});
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(KEY_NUMOFCHAMPS, noOfChamps);
}
public void startChampActivity(){
Intent intent = new Intent(DrawActivity.this,ChampsActivity.class);
intent.putExtra(ChampsActivity.EXTRA_NUMOFCHAMPS,noOfChamps);
startActivity(intent);
}
Champ Activity - Draws the champs based on random no. and display it
public class ChampsActivity extends Activity {
private final static double fourStarHero = 0.04;
private final static double threeStarHero = 0.2;
private static int[] champCount = {0, 0, 0};
private static int noOfDraws=0;
private TextView mShowResult;
private static final String[] champsList = {"Thor", "Gamora", "Iron Fist", "Iron Man",
"Star Lord", "Dr. Strange", "Drax", "Juggernaut", "Storm", "Wolverine", "Hulk",
"Magneto", "Ultron", "Daredevil", "Capt. America", "Rocket Racoon","Magic","Black Panther"};
public static final String EXTRA_NUMOFCHAMPS = "ChampsAct_NoOfChamps";
public static final String TAG ="ChampsAct";
private static StringBuilder drawResultSet = new StringBuilder();
public static String getChampList() {
StringBuilder result = new StringBuilder();
for (int i = 0; i < champsList.length; i++) {
result.append(champsList[i].toUpperCase()).append(", ");
}
return result.toString();
}
private static String getChampName() {
int rand = (int) (Math.random() * champsList.length);
return champsList[rand].toUpperCase();
}
private static void getChamps(int noOfChamps) {
drawResultSet.setLength(0);
for (int i = 0; i < noOfChamps; i++) {
double rand = Math.random();
if (rand < fourStarHero) {
champCount[2]++;
drawResultSet.append("4 Star ").append(ChampsActivity.getChampName()).append("\n");
} else if (rand < threeStarHero) {
champCount[1]++;
drawResultSet.append("3 Star ").append(ChampsActivity.getChampName()).append("\n");
} else {
champCount[0]++;
drawResultSet.append("2 Star ").append(ChampsActivity.getChampName()).append("\n");
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_champs);
noOfDraws = getIntent().getIntExtra(EXTRA_NUMOFCHAMPS,1);
getChamps(noOfDraws);
//Log.d(TAG, drawResultSet.toString());
mShowResult = (TextView) findViewById(R.id.result_heroes);
mShowResult.setText(drawResultSet.toString());
}
}

Android - call OnSaveInstanceState from another class than main

I am creating some EditTexts with button, I created a class which implements OnClickListener, and I want to save those EditTexts after screen rotation but they always disappear. I know that
Activity on rotation is destroyed and created again
I cant save EditText in Bundle since it does not implement Parcelable or something like that
So I tried to save at least their ID's and Text they have in them with the onSaveInstanceState(Bundle savedInstanceState)
but it is not called because it is not in main class, but in another called ViewControl. I need to save some private variables (text and ids) so that is the reason why I have this method inside my class. I tried to call this method from another onSaveInstance which is in main but no luck neither. Can you tell me some easy way to programatically create EditTexts one below another and KEEP them after screen rotation? I really cant find any easy way...
Main class
public class MainActivity extends Activity {
private ViewControl vc;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vc = new ViewControl(this);
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
vc.onSaveInstanceState(savedInstanceState);
}
ViewControl class
import java.util.ArrayList;
public class ViewControl extends Activity implements View.OnClickListener{
private Button btn;
private RelativeLayout rl;
private Activity act;
private ArrayList<Integer> id;
private ArrayList<String> userpath;
private int lastId;
public ViewControl(Activity activity) {
this.act = activity;
this.id = new ArrayList<Integer>();
this.userpath = new ArrayList<String>();
this.rl = (RelativeLayout)act.findViewById(R.id.layout);
this.btn = (Button)act.findViewById(R.id.btn);
this.id.add(Integer.valueOf(R.id.btn));
this.btn.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(id.size() != 1)
lastId = id.get(id.size() - 1);
else
lastId = R.id.btn;
RelativeLayout.LayoutParams par = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
par.addRule(RelativeLayout.BELOW, lastId);
EditText et = new EditText(act);
et.setId(++lastId);
id.add(Integer.valueOf(lastId));
et.setText(Integer.toString(lastId));
rl.addView(et, par);
lastId = et.getId();
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putIntegerArrayList("ids", id);
savedInstanceState.putStringArrayList("userpaths", userpath);
savedInstanceState.putInt("lastId", lastId);
Toast.makeText(act, "Onsave", Toast.LENGTH_LONG).show();
}
#Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
this.id = savedInstanceState.getIntegerArrayList("ids");
this.userpath = savedInstanceState.getStringArrayList("userpaths");
this.lastId = savedInstanceState.getInt("lastId");
Toast.makeText(act, "Onrestore", Toast.LENGTH_LONG).show();
for(int i = 0; i < id.size(); i++)
{
RelativeLayout.LayoutParams par = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
par.addRule(RelativeLayout.BELOW, lastId);
EditText et = new EditText(act);
et.setId(this.id.get(i));
}
}
}
The calls are in the wrong order (both in MainActivity and ViewControl). First you should add your data, then pass the Bundle to super to save it (see the docs here). (Your onRestoreInstanceState is OK)

Array of subclasses and onClick()

I want to create by code an array of objects that are subclasses of Button.
public class MyButton extends Button {
private Context ctx;
private int status;
public MyButton(Context context) {
super(context);
ctx = context;
status = 0;
}
private click() {
status = 1;
// OTHER CODE THAT NEEDS TO STAY HERE
}
}
In the main activity I do this:
public class myActivity extends Activity {
private MyButton[] myButtons = new MyButton[100];
#Override
public onCreate(Bundle si) {
super.onCreate(si);
createButtons();
}
private void createButtons() {
for (int w=0; w<100; w++) {
myButtons[w] = new MyButton(myActivity.this);
myButtons[w].setOnClickListener(new View.onClickListener() {
public void onClick(View v) {
// ... (A)
}
});
}
}
}
Now I want the click() method inside MyButton to be run each time the button is clicked.
Seems obvious but it is not at my eyes.
If I make the click() method public and run it directly from (A), I get an error because myButtons[w].click() is not static and cannot be run from there.
In the meantime, I an not able to understand where to put the code in the MyButton class to intercept a click and run click() from there. Should I override onClick? Or should I override onClickListener? Or what else should I do?
How can I run click() whenever one of myButtons[] object is clicked?
Thanks for the help.
You can cast View v you got in listener to MyButton and call click on it:
private void createButtons() {
View.OnClickListener listener = new View.onClickListener() {
public void onClick(View v) {
((MyButton) v).click();
}
};
for (int w=0; w<100; w++) {
myButtons[w] = new MyButton(myActivity.this);
myButtons[w].setOnClickListener(listener);
}
}
you can add:
View.onClickListener onclick = new View.onClickListener() {
public void onClick(View v) {
((MyButton)v).click();
//since v should be instance of MyButton
}
};
to your Activity
then use:
myButtons[w].setOnClickListener(onclick);
//one instance of onclick is enough, there is no need to create it for every button
in createButtons()
but ... why, oh why array of buttons we have ListView in android ...

onClickListener not working in my activity

My layout has 13 TextViews which on click changes the ListView Items.
Here is my activity:
public class ExampleActivity extends ListActivity implements
OnClickListener {
private String[] sa = new String[100];
private ListView lv;
private Context context = this;
private ArrayAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new LongOperation().execute("1");
lv = getListView();
}
private class LongOperation extends AsyncTask<String, Void, String> {
private ProgressDialog dialog = new ProgressDialog(
ExampleActivity.this);
#Override
protected String doInBackground(String... params) {
int i = Integer.parseInt(params[0]);
for (int n = 0; n < 100; n++) {
if (i != 5 && i != 10) {
sa[n] = "Item" + i;
} else {
}
}
return params[0];
}
#Override
protected void onPostExecute(String result) {
adapter = new ArrayAdapter<Object>(context,
android.R.layout.simple_list_item_1, sa);
lv.setAdapter(adapter);
this.dialog.dismiss();
}
#Override
protected void onPreExecute() {
this.dialog.setMessage("Please wait");
this.dialog.show();
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
public void onClick(View v) {
Log.d("onClick", v.getId() + "**");
int id = v.getId();
switch (id) {
case R.id.tv1: {
new LongOperation().execute("1");
}
case R.id.tv2: {
new LongOperation().execute("2");
}
case R.id.tv3: {
new LongOperation().execute("3");
}
case R.id.tv4: {
new LongOperation().execute("4");
}
case R.id.tv5: {
new LongOperation().execute("5");
}
case R.id.tv6: {
new LongOperation().execute("6");
}
case R.id.tv7: {
new LongOperation().execute("7");
}
case R.id.tv8: {
new LongOperation().execute("8");
}
case R.id.tv9: {
new LongOperation().execute("9");
}
case R.id.tv10: {
new LongOperation().execute("10");
}
case R.id.tv11: {
new LongOperation().execute("11");
}
case R.id.tv12: {
new LongOperation().execute("12");
}
case R.id.tv13: {
new LongOperation().execute("13");
}
}
}
}
the listView is populated as item1 when i launch the app. but when i click on any of the TextViews, the onClick method is not triggered. i checked it using a Log.
Thank You.
Because you are not registering onClickListener with your TextViews hence your TextViews are not getting Clicked event.
For this you have to do something like,
onCreate()
{
TextView tv1 = (TextVIew)findViewById(R.id.tv1);
tv1.setOnClickListener(this);
Better Solution:
In your Activity's xml Layout File,
in your all TextView put attribute android:onClick="textClick"
Now remove onClickListener from your Activity and just write
public void textClick(View TextView)
in your activity. Then you don't have to register onClicklistener for all TextView. Android does itself for you..
This is a sample program provided when you use implements OnClickListener
public class ExampleActivity extends Activity implements OnClickListener {
protected void onCreate(Bundle savedValues) {
Button button = (Button)findViewById(R.id.corky);
button.setOnClickListener(this); // have a look on this line. registering.
}
// Implement the OnClickListener callback
public void onClick(View v) {
// do something when the button is clicked
}
}
this happens because you not using the setOnClickListener() for your TextViews
Add this static function in your activity class, This work for me in my MainActivity.java
public class MainActivity extends AppCompatActivity {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}

Categories

Resources