Pass variable from Recyclerview-Holder to Mainactivity - java

I tried a lot of things but I can't get it to work... I try to pass this String Variable (when i click Item in RecyclerView) to my MainActivity.
What works bad is calling the function (OnRecyclerViewItemClick) and changing the variable(GetUrlFromItem). My version of Android Studio is 2.3.3
I really need do this:
My RecyclerView:
public class viewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView titulo;
Button playbtn01;
List<Fuente> ListaObjeto;
public viewHolder(View itemView,List<Fuente> datos) {
super(itemView);
ListaObjeto = datos;
titulo = (TextView) itemView.findViewById(R.id.texto);
playbtn01 = (Button) itemView.findViewById(R.id.playbtn00);
playbtn01.setOnClickListener(this);
}
#Override
public void onClick(View view) {
int position = getAdapterPosition();
Fuente objeto = ListaObjeto.get(position);
if (view.getId() == playbtn01.getId()) {
MainActivity mainActivity = new MainActivity:
mainActivity.OnRecyclerViewItemClick(); /// initiate Void in Main
mainActivity.GetUrlFromItem = objeto.GetUrl; //Change Variable of Main
}
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
public String GetUrlFromItem;
public void OnRecyclerViewItemClick() {
if (GetUrlFromItem == "..."){
doSomething...
}
}
}

There are two big problems that I see.
The first is how you get a MainActivity instance to work with. In your question, you have this line of code:
MainActivity mainActivity = new MainActivity:
Calling new is going to do exactly what it sounds like: create a new instance of the MainActivity class. You do not want a new instance! You want your alive and running instance.
There are a handful of ways to get ahold of your alive and running MainActivity, but probably the simplest one for now is going to be casting your ViewHolder's itemView's Context. So instead of the above, write something like this:
MainActivity mainActivity = (MainActivity) itemView.getContext();
The second big problem is in the next two lines:
mainActivity.OnRecyclerViewItemClick();
mainActivity.GetUrlFromItem = objeto.GetUrl;
The problem here is the order of these two statements. Because you invoke mainActivity.OnRecyclerViewItemClick() before setting the value of mainActivity.GetUrlFromItem, the value will not be updated when OnRecyclerViewItemClick() is executed.
Simply swap the order of these two lines.

Related

Java class extends MainActivity but findViewById comes back null?

This class extends my main Activity.
public class Numbers extends MainActivity{
public ArrayList<ImageView> getNumbers () {
ArrayList<ImageView> numbers = new ArrayList<>();
ImageView one = (ImageView) findViewById(R.id.one);
numbers.add(one);
return numbers;
}
And I've done some digging but can figure out why my variable "one" is coming back null.
My MainActivity has a ContentView set.
This is the content of my onCreate in MainActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageView start = (ImageView) findViewById(R.id.start);
sceneRoot = (ViewGroup) findViewById(R.id.scene_root);
questionView = findViewById(R.id.questionView);
startView = findViewById(R.id.startView);
gameOverView = findViewById(R.id.gameOver);
animSlide = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.slide);
animSlide.setAnimationListener(this);
animZoom = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.zoom_fade);
animZoom.setAnimationListener(this);
set.addTransition(new Fade())
.addTransition(new Slide(Gravity.RIGHT));
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getQuestion();
TransitionManager.beginDelayedTransition(sceneRoot, set);
startView.setVisibility(View.GONE);
questionView.setVisibility(View.VISIBLE);
}
});
}
public void getQuestion (){
time = (TextView) findViewById(R.id.timeBar);
time.startAnimation(animSlide);
}
I don't call getNumbers() until after start has been clicked and the animation has started.
public void onAnimationStart(Animation animation){
if(animation == animSlide) {
final Questions questions = new Questions();
Numbers n = new Numbers();
for (int i = 0; i < n.getNumbers().size(); i++) {
n.getNumbers().get(i).setVisibility(View.GONE);
n.getNumbersTen().get(i).setVisibility(View.GONE);
}
n.getNumbers().get(0).setVisibility(View.VISIBLE);
EDIT:
If anyone was wondering, I got it to work by extending the class as a Fragment instead of my MainActivity. Then I just used the fragment in my xml.
Because you extended an Activity class doesn't mean setContentView gets called for that class also. It will only do so if properly started and you call super.onCreate(bundle) from your own implementation of onCreate within Numbers
Basically, you should never new any Activity. It has no life-cycle, and therefore no content view, so findViewById just won't work.
Numbers n = new Numbers();
You could not extend anything and have a data-only class around your list of images.
public class Numbers {
private List<ImageView> numbers = new ArrayList<ImageView>();
public Numbers() {}
public void addNumber(ImageView v) { numbers.add(v); }
public List<ImageView> getNumbers() { return numbers; }
}
And from MainActivity you can find and add as you want.
Number n = new Numbers();
n.addNumber((ImageView) findViewById(R.id.one));
However, I don't know if that is useful, really...
Maybe a Fragment would serve a better purpose if you want a "sub-view" of your Activity, but it's hard to tell.

Spinner in Custom Function for Android with java

I am confused about calling the spinner widget through a custom function. I am create an app in which I use spinner 20-35 times a spinner widget in single layout or activity. So for this i want to avoid the spinner code repetition again and again. i am creating a method for this i add the items to the spinner but i want to pass item value on select to other activity which bind to that class
Here is my code
Spin_tester.class
public class Spin_tester {
public String result;
public Context ctx;
public Spin_tester(Spinner spinner, final ArrayList<String> arraylist, final Context ctx , final String value) {
this.ctx= ctx;
ArrayAdapter<String> adpts =
new ArrayAdapter<String>(ctx, android.R.layout.simple_dropdown_item_1line,arraylist);
spinner.setAdapter(adpts);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
result = arraylist.get(position);
value = result ; // This is not working
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
}
Test_Activity.class
public class Test_Activity extends AppCompatActivity {
ArrayList<String> data_list = new ArrayList<>();
Spinner spins;
String value;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
spins = (Spinner)findViewById(R.id.spinner);
data_list.add("1");
data_list.add("2");
data_list.add("3");
data_list.add("4");
Spin_tester asd = new Spin_tester(spins,data_list,this,value);
TextView txt = (TextView)findViewById(R.id.textView17);
}
}
Please help
Thanks in advance
Java is a pass-by-value language, not pass-by-reference. What this means is that setting value in setOnItemSelectedListener will only change value within that method — the result won't be passed back anywhere.
I see that you've place the result in result. That is where the calling program will find the answer.
Remove all instances of value from Spin_tester and Test_Activity and then have your main activity get the result from asd.result
I'm going to get a little meta at this point: I've only answered the question you actually asked, but this code is wrong on so many levels that you're never going to get it to work. I strongly suggest you work your way through the examples and tutorials in the documentation before you try to proceed any further.

Im missing some global variables

I've got 2 activities and a class that extends Application where I'm trying to store global variables with a kind of setter getter functions.
The main activity sets some views and a chart; then calls the second activity which should be setting values to be used afterwards on the previous chart.
Then pressing backbutton and returning to the previous activity onRestart is called and the chart is refreshed.
The problem is I lose my theorically global variables somewhere. Debugging i realized that the functions work perfectly fine while im adding values in the second activity but when I return to the first activity globalXCount returns '0' again. Why is that?
I think im missunderstanding some point regarding lifecycles.
I attach some fragments of the code.
First activity:
public class MainActivity extends Activity {
Global glObj = new Global();
CombinedChart mChart;
private int itemcount;
float displayed;
private final List<String> mMonthList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
itemcount = ((Global) this.getApplication()).getGlobalXCount();
displayed = itemcount/20;
mChart = (CombinedChart) findViewById(R.id.mchart);
populateHeaderList();
setChartSettings();
Intent intent = new Intent(MainActivity.this, QandA.class);
startActivity(intent);
}
#Override
protected void onRestart() {
super.onRestart();
itemcount = ((Global) this.getApplication()).getGlobalXCount();
displayed = itemcount/20;
populateHeaderList();
setChartSettings();
}
Second activity:
public class QandA extends Activity {
Global glObj = new Global();
ViewFlipper flipper;
private float lastX;
...
}else{
//TODO If all information if correctly filled
trainedmins = et1.getText().toString();
localLineValue = Integer.parseInt(trainedmins) * Integer.parseInt(statusQ1);
//Add values to lines
glObj.setLineXvalues(localLineValue);
// TODO Add new Bar value //
//Add 1 more value to count
glObj.addGlobalXCount();
}
...
Global class:
public class Global extends Application {
//TODO
public Integer globalXCount;
private List<Integer> lineXvalues = new ArrayList<>();
private List<Integer> barXvalues = new ArrayList<>();
//////
public Integer getGlobalXCount() {
if (this.globalXCount == null){
this.globalXCount = 0;
return this.globalXCount;
}else{
return this.globalXCount;
}
}
public void addGlobalXCount() {
if (this.globalXCount == null){
this.globalXCount = 0;
}else{
this.globalXCount = this.globalXCount + 1;
}
}
Thanks in advance.
First of all, register your custom Application context in AndroidManifest.xml within the <application>-tag.
<application
android:name="<your_package>.Global" ...>
Access the global application context within your activities like this:
Global glObj = (Global) getApplicationContext();
glObj.addGlobalXCount();
Do not create a new instance with new! Always retrieve the instance via getApplicationContext().
Furthermore, I would suggest you to initialize your class field glObj within the onCreate()-method of your Activities.

Calling values from an array in the string.xml file in an Android app

I have built a fortune cook app that previously currently has values hardcoded into an array
FortuneActivity.java
package juangallardo.emofortunecookie;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.util.Random;
public class FortuneActivity extends Activity {
private FortuneBox mFortuneBox = new FortuneBox();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fortune);
// Declare our View variables and assign them the Views from the layout file
final TextView fortuneLabel = (TextView) findViewById(R.id.fortuneTextView);
Button showFortuneButton = (Button) findViewById(R.id.showFortuneButton);
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View view) {
String fortune = mFortuneBox.getFortune();
// Update the label with dynamic fortune
fortuneLabel.setText(fortune);
}
};
showFortuneButton.setOnClickListener(listener);
}
}
FortuneBox.java
package juangallardo.emofortunecookie;
import java.util.Random;
public class FortuneBox {
public String[] mFortunes = {
"What is the point?",
"Sometimes it is best to just sleep in.",
#98 other fortunes...
};
// Methods (abilities)
public String getFortune() {
String fortune = "";
// Randomly select a fortune
Random randomGenerator = new Random();
int randomNumber = randomGenerator.nextInt(mFortunes.length);
fortune = mFortunes[randomNumber];
return fortune;
}
}
The problem is that now I want to add a Spanish version. So I realize that i should add that array into the strings.xml.
I looked up string resources on the Android developer page. and it gave me the idea to add this to my code
strings.xml
<string-array name="emo_fortunes">
<item>What is the point?</item>
<item>Sometimes it is best to just sleep in.</item>
</string-array>
But now I am stuck on where to add this part that has the part about Resources, etc.
I followed along to a tutorial from Treehouse about strings but my app kept crashing.
Basically the change that I made was to make the original array into
FortuneBox.java
# above unchanged from previous code
public String[] mFortunes;
# below unchanged from previous code
FortuneActivity.java
# same imports as before
public class FortuneActivity extends Activity {
private FortuneBox mFortuneBox = new FortuneBox();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fortune);
Resources resources = getResources();
final String[] mFortuneBox = resources.getStringArray(R.array.emo_fortunes);
// Declare our View variables and assign them the Views from the layout file
final TextView fortuneLabel = (TextView) findViewById(R.id.fortuneTextView);
Button showFortuneButton = (Button) findViewById(R.id.showFortuneButton);
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View view) {
String fortune = mFortuneBox.getFortune();
// Update the label with dynamic fortune
fortuneLabel.setText(fortune);
}
};
showFortuneButton.setOnClickListener(listener);
}
}
These were my errors, but not sure where to go from here as I am new to Android and I have not touched Java since college.
log
FortuneActivity.java
FortuneBox.java
Mikki has the right answer, but it is a little confusing. In your code above, you are using the same name for two different variables: mFortuneBox. This is the root of your trouble:
private FortuneBox mFortuneBox = new FortuneBox();
...
final String[] mFortuneBox = resources.getStringArray(R.array.emo_fortunes);
Change the second one to a different name, like this, and the errors go away:
final String[] fortunes = resources.getStringArray(R.array.emo_fortunes);
However, you still aren't using these fortunes from the array anywhere. You can actually delete fortunes from your Activity and move it to your FortuneBox class instead. This is slightly tricky, though, as you need to know what the context is to get a string array resource in your other class. The context is the Activity, so you need to pass this along as a parameter when you create your FortuneBox object.
I'd recommend a slight restructuring. Below are the two files that should work for you:
FortuneActivity.java
public class FortuneActivity extends Activity {
private FortuneBox mFortuneBox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fortune);
mFortuneBox = new FortuneBox(this);
// Declare our View variables and assign them the Views from the layout file
final TextView fortuneLabel = (TextView) findViewById(R.id.fortuneTextView);
Button showFortuneButton = (Button) findViewById(R.id.showFortuneButton);
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View view) {
String fortune = mFortuneBox.getFortune();
// Update the label with dynamic fortune
fortuneLabel.setText(fortune);
}
};
showFortuneButton.setOnClickListener(listener);
}
}
FortuneBox.java
public class FortuneBox {
public String[] mFortunes;
public FortuneBox(Context context) {
Resources resources = context.getResources();
mFortunes = resources.getStringArray(R.array.emo_fortunes);
}
// Methods (abilities)
public String getFortune() {
String fortune = "";
// Randomly select a fortune
Random randomGenerator = new Random();
int randomNumber = randomGenerator.nextInt(mFortunes.length);
fortune = mFortunes[randomNumber];
return fortune;
}
}
Your problem is simple. You can not access a non-final from an inner class (in this case your OnClickListener).
final String[] mFortuneBox = resources.getStringArray(R.array.emo_fortunes);
Try just changing the line to look like this one above.
Hope it helps.
The mFortuneBox variable in the previous way you have used is an object of FortuneBox class and hence this call mFortuneBox.getFortune() works.
In the later changed code, you have made mFortuneBox variable a reference to an Array of strings. But still tried calling mFortuneBox.getFortune(). 'getFortune()' is a method of FortuneBox class right, so you can call it with an object of Forune Box class itself.
Try doing this:
final String[] fortuneArray = resources.getStringArray(R.array.emo_fortunes);
and
private FortuneBox mFortuneBox = new FortuneBox();
Now call mFortuneBox.getFortune(fortunearray) sending it this array to the getfortune method.
Now let the getFortune() method randomly pick one from this array passed and return the random string picked

Creating a BitmapDrawable in a static context

Please help!
I have a problem with creating a BitmapDrawable in a static context.
I am creating an android app for a student contest and since the MainActivity class starts
to look "dirty" (having lots of code in it) I decided to make MainActivityLayout class that extends the MainActivity. Basicly I moved some methods (the ones for setting layouts) from MainActivity to MainActivityLayout class. The problem is with resize() method where I use BitmapDrawable constructor wich is "bugging me slowly" because needs a reference to resources in order to resize properly the bitmap.
The MainActivity class :
public class MainActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getLayoutOne();
MainActivityLayouts.setLayoutOne();
getLayoutTwo();
MainActivityLayouts.setLayoutTwo();
}
private void getLayoutOne(){
//here I get the layouts id using findViewById() method
}
private void getLayoutTwo(){
//here I get the layout 2 id using findViewById() method
}
protected static Drawable resize(Drawable image,int xSize,int ySize) {
Bitmap b = ((BitmapDrawable)image).getBitmap();
Bitmap bitmapResized = Bitmap.createScaledBitmap(b, xSize, ySize, false);
return new BitmapDrawable(getResources(),bitmapResized);
}
}
The MainActivityLayout class:
public class MainActivityLayouts extends MainActivity{
public MainActivityLayouts(){
// ...
}
protected final static void setLayoutOne(){
Drawable drawableOne = ImageViewOne.getDrawable();
//here is the problem...cannot make a static refference...
//getResources() from resize method from MainActivity to be more specific
drawableOne = resize(drawableOne,100,100);
ImageViewOne.setImageDrawable(drawableOne);
}
protected final static void setLayoutTwo(){
Drawable drawableTwo = ImageViewTwo.getDrawable();
//here is the problem...cannot make a static refference...
//getResources() from resize method from MainActivity to be more specific
drawableTwo = resize(drawableTwo,200,200);
ImageViewTwo.setImageDrawable(drawableTwo);
}
Is there any solution to my problem? Resizing in another mode or can I avoid creating a BitmapDrawable and still obtain the same effect?
Any critic is highly appreciated :).

Categories

Resources