Android app crashes when defining and setting element properties - android

My app is crashing. What am I doing wrong?
I am using an AsyncTask in a class fetchsSchools.
public class fetchSchools extends AsyncTask<Void, Void, ArrayList<String>>{
#Override
protected ArrayList<String> doInBackground(Void... arg0) {
ArrayList<School> schools = new ArrayList<School>();
ArrayList<String> schoolNames = new ArrayList<String>();
... code omitted for conciseness...
return schoolNames;
}
In this class I have an onPost Execute, my code gets to this, if I remark out the cls2 lines my app runs:
public void onPostExecute(ArrayList<String> schoolNames) {
MainActivity cls2=new MainActivity();
cls2.updateSpinner(schoolNames);
cls2.switchScreens();
}
The above fires off these two outines back in MainActivity which crash the app:
public void updateSpinner(ArrayList<String> schoolNames) {
Spinner schoolSpinner = (Spinner)findViewById(R.id.school_spinner);
schoolSpinner.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_spinner_dropdown_item, schoolNames));
}
public void switchScreens() {
ProgressBar progressBar1 = (ProgressBar)findViewById(R.id.progressBar1);
progressBar1.setVisibility(View.GONE);
TextView loading_label = (TextView)findViewById(R.id.loading_label);
loading_label.setVisibility(View.GONE);
}
Eclipse isn't showing any coding errors. Am I creating and acting on these variables correctly?

Though you have not given code for MainActivity and logcat. Seeing your code looks like MainActivity extends Activity. If so you cannot call
MainActivity cls2=new MainActivity();
MainActivity has to be initialized by android framework with appropriate context. Calling constructor yourself will not call any lifecycle methods of the Activity.
So all subsequent calls that use Context will fail, especially findViewByid
You need to do startActivity instead of what you are doing.
Edit:
Create a constructor in Asynctask pass MainActivity when instantiating and assign like below and remove new MainActivity line
public class fetchSchools extends AsyncTask<Void, Void, ArrayList<String>>{
MainActivity cls2;
fetchSchools(MainActivity activity){
cls2 = activity;
}
#Override
protected ArrayList<String> doInBackground(Void... arg0) {
ArrayList<School> schools = new ArrayList<School>();
ArrayList<String> schoolNames = new ArrayList<String>();
... code omitted for conciseness...
return schoolNames;
}
public void onPostExecute(ArrayList<String> schoolNames) {
cls2.updateSpinner(schoolNames);
cls2.switchScreens();
}
}
In MainActivity, you call
new fetchSchools(mMainActivity).execute(param);

If this is a seperate class from that your main activity, then you're trying to findViewById from where? You probably get NullPointerException on very first line of onPostExecute which is this one:
cls2.updateSpinner(schoolNames);
Because you try to find a view in this method. But you do not have any parent view which contains the view that you seek to find.
So i would suggest you to move this fetchSchools class as a private inner class of your mainActivity. so you'll be able to find those views globally and set them however you want.

Related

Communication between two adapters in android?

I have two views In a single activity StackView and Gridview and 2 corresponding adapters .when I clicked on StackView item it should flip the grid item in Gridview and vice versa?
// activity classs
public class SampleActivity extends Activity implements
OnGridChangeListener {
public void onCreate(bundle){
// replace this with your adapter class.
Adapter adapter = new adapter(this);
}
#override
public void OnGridChange(){
//here you go.
// write code to do what you want.
}
// interface to communicate with activity
public interface OnGridChangeListener {
public void OnGridChange()
}
// adaptor class
public class Adaptor extends "you apapter class to extend"{
OnGridChangeListener onGridChangeListener ;
public Adapter(OnGridChangeListener listener){
onGridChangeListener =listener
}
public getView(){
public void onclick(){
onGridChangeListener.OnGridChange("pass you data");
}
}
}
As per your question this is what i get -
You have a Activity with two independent views which has their own adapters. So when there is changes in one of the adapter you want it to be reflected into another adapter.
The simple solution for your query would be -
When there is a change in first adapter you reflect the change to the activity. after that call the function in the second adapter to reflect the change you want in second adapter.
For this you have to define an interface in first adapter and implement this is activity.
When the first adapter changes call the interface method and this will reflect in activity.
Then call method in second adapter to do the changes you want.
Code example -
MainActivity.Java
public class MainActivity extends AppCompatActivity implements FirstAdapter.callBackMethods {
FirstAdapter firstAdapter;
SecondAdapter secondAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
firstAdapter = new FirstAdapter(MainAtivity.this.getApplicationContext());
//do all the declaration and operation of first adapter. Pass context along with your required params.
secondAdapter = new SecondAdapter();
//do all the declaration and operation of second adapter.
}
//callback method of first adapter
#override
public void callback(){
//changes have been done in FirstAdapter and this methos is fired.
//now do do the changes in SecondAdapter as per req.
if(secondAdapter != null){
secondAdapter.reflectChanges();
}
}
}
FirstAdapter.class
I am taking example of recylerview adapter.
public class FirstAdapter extends RecyclerView.Adapter<FirstAdapter.ViewHolder>{
public FirstAdapter(Context context){
this.context=context;
}
/*
all the boilerplate codes and business logic
*/
//when you want to reflect the changes
callBackMethods callBackMethods = (callBackMethods) context;
callBackMethods.callback();
//this will fireup the implementation in the MainActivity.
public interface callBackMethods{
public void callback();
}
}
SecondAdapter.class
This is where the changes will be reflected.
public class SecondAdapter extends RecyclerView.Adapter<SecondAdapter.ViewHolder>{
/*
all the boilerplate codes and business logic
*/
public void reflectChanges(){
/*
This method will be called from the MainActivity. pass whatever params you want to pass from Activity and do the changes you want to do in the SecondAdapter.
*/
}
}
I hope this solves your problem. Happy coding...

Add view outside of onCreate in android

How can I add view bye function, outside of onCreate() in Android ?
My MainActivity.java
public class Main extends Activity {
static RelativeLayout mainRel;
static LinearLayout ll;
static TextView title;
static Context context;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
RelativeLayout mainRel=(RelativeLayout) findViewById(R.id.mainRel);
}
public static void refresh(){
LinearLayout ll = new LinearLayout(this); // actually "this" just works in onCreate;
TextView title = new TextView(this);// actually "this" just works in onCreate;
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.addView(title);
title.setText("TV");
mainRel.addView(ll);
}
}
}
Thanks in advance
Usually, UI-related operations are not done in static methods. If you remove the static keyword, the this pointer will work even outside onCreate().
If you insist on keeping the static keyword (because you need the method to be static) then, you should pass a Context parameter to the method, by changing it to refresh(Context context)
Edit: if you need to call this method from another class, you might want to create a reference to your Main Activity and pass it to this other class, then call myMainActivity.refresh()
Calling static method is really bad idea.
Instead you can provide reference of the Activity to your AsyncTask in constructor. Then call non-static refresh() method from AsyncTask#onPostExecute().
When you store reference to Activity in AsyncTask use WeakReference. In case your activity is destroyed while background task is working, it won't be held in memory till background ends.
public class YourAsyncTask extends AsyncTask<Void, Void, Void> {
private WeakRefrence<Main> mainRef;
public YourAsyncTask(Main activity) {
mainRef = new WeakReference<Main>(activity);
}
protected void onPostExecute(Void result) {
Main main = mainRef.get();
if (main != null) {
main.refresh();
}
}
}

AsyncTask - How to access to GUI elements from OnPostExecute

I have an application with the following workflow :
Main activity where the user types his research keywords -> Click on the "search" button -> Starting an AsyncTask making a query on a webservice (query handled within the doInBackground method) -> Creation of a new activity.
Now I want to display the webservice result within this new activity. How can I do ? I know I should to use "onPostExecute" but the AyncTask object has not any access to this new Activity from the "onPostExecute" method. Any clues ?
Thank you !
How to access to GUI elements from OnPostExecute
Make a activity and get the view in onCreate(bundle) and Define a AsyncTask as inner class.
public class MainActivity extends Activity
{
TextView textView;
public void onCreate(Bundle bundle){
....
textView = (TextView)findViewById(R.id.textview);
}
Declare the AsyncTask inside this class.
private class UpdateUiAsyncTask extends AsyncTask<Void, Void, Void>{
........
.....
protected void onPostExecute(String result) {
textView.setText(result);
}
}
}

pass UI Controls from activity to a class

I stuck at this issue many times and I passed the problem in different ways and I'm not sure that I made it in the right way.
I simplified the problem in a the following example. I know that I can pass only the data to the class but I do want to pass the editText cause I have this problem with more difficult UI controls.
mainactivity.java
public class mainactivity extends Activity {
public EditText clickEditText;
int count =0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
newTxt();
}
public void newTxt() {
txt = new MyText(context);
txt.updateTextEdit("Main Activity");
}
}
myText.java
public class MyText
{
private Context _context;
// constructor
public MyText(Context context)
{
_context = context;
}
public void updateTextEdit(String str)
{
private EditText strEditText;
strEditText= (EditText)findViewById(_context.R.id.editTextClick); // ????
strEditText.setText(str + " and myTxt");
}
}
if you could explain me how to fix the updateTextEdit function. i passed the context of the main activity. How can I change the editText? Thank you very much!!!
If you really want to do this this way, you need to save a reference to Activity, not Context. Like this:
public class MyText
{
private Activity _activity;
// constructor
public MyText(Activity activity)
{
_activity= activity;
}
public void updateTextEdit(String str)
{
private EditText strEditText;
strEditText= (EditText)activity.findViewById(R.id.editTextClick);
strEditText.setText(str + " and myTxt");
}
}
and in newTxt() you will need to change:
txt = new MyText(context);
to:
txt = new MyText(this);
But wouldn't it be easier to just put this method inside your activity? Why do you want it in another class? If it really needs to be in another class, you could make that class an inner class of your activity and you would still have access to the activity's methods and member variables.
There's a similar question here
How to access Activity UI from my class?
You didn't say how you obtained the context, you should use this and get the mainactivity in the other class. not context.
then you can call runOnUIThread to perform UI updates.

Is it possible to access an object of an activity fom other place?

This maybe a stupid idea, but does anyone know is it possible to access one activity's object form other places?
To be specific, lets say if you have an activity A (with a textView t) and you create a normal java class B.
At onCreate, you start to run B for some calculation like below,
public class MyActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
t = (TextView)findViewById(R.id.outputtext);
Somejava B = new Somejava();
B.run();
}
}
Is there a way for B to update the textView?
I know the simple way (maybe the correct way) is to return the result from B class and use t.setText(result) in MyActivity, but I'm just want to know is it possible to update the textview in B?
Use Intent or public static variables
can simply pass activity refernce to b in constructor and create the method in your acitivty to update textview. if you using another thread not forgot to use handler or other ways to update UI thread.
Yes, it is possible if the Activity's field is public and post the UI changes in a public Handler created on the first Activity but in facts, it's really ugly to do that...
You can use startActivityForResult(...) to notify an other activity how the process has passed with some serialiezable data in the Bundle extras of the Intent and catch the result in the overrided method onActivityResult(...)...
For a "normal java class" B I would work with interfaces
public interface SomejavaListener{
void onSomejavaFinish(Object result);
}
public class MyActivity implements SomejaveFinish extends Activity {
TextView t;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
t = (TextView)findViewById(R.id.outputtext);
Somejava B = new Somejava();
B.run(MyActivity.this); //notice the extra argument!
}
public void onSomejavaFinish(Object result){
t.setText("updated! ^,^");
}
}
public class Somejava {
//...
public void run(SomejavaListener callback){
//working working
callback.onSomejavaFinish( new Object() );
}
}
However in respect to the android environment the question is sitting in I got the feeling maybe an AsyncTask would be the right thing for you. It has an doInBackground method to do work and not spoiling your UI Thread (resulting in ANR Errors.)
Another advantage is the onPreExecute and onPostExecute methods are running in the UI Thread itself again, so it just takes a blink to update your TextView
public class MyActivity extends Activity {
TextView t;
private class MyAsyncTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... void) {
//do your stuff
return null
}
protected void onPostExecute(Void void) {
MyActivity.this.t.setText("updated ^^v");
}
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
t = (TextView) findViewById(R.id.outputtext);
MyAsyncTask myAsyncTask = new MyAsyncTask();
myAsyncTask.execute();
}
}

Categories

Resources