2016-10-20 2 views
0

Привет, я сделал простое приложение в Android, которое подключается к серверу и получает список сообщений, после чего у меня есть spinner, который заполняется заголовком каждого сообщения, и вы можете выбрать один из них.Spinner не отображает выбранный элемент

Все работает до тех пор, пока я не должен выбрать сообщение, я открываю spinner, он показывает все названия, которые я выбираю, и ничего не происходит, сообщение не выбрано в spinner, и тексты не меняются Я читал, как 10 постов о блесны не показаны элементы, но я не мог заставить его работать, пожалуйста, помогите мне, это мой Java-код:

package com.example.lagarto.blog; 

import android.graphics.Color; 
import android.os.AsyncTask; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.AdapterView; 
import android.widget.ArrayAdapter; 
import android.widget.TextView; 

import org.w3c.dom.Text; 

import java.sql.Connection; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Statement; 
import java.util.ArrayList; 
import android.util.Log; 
import android.widget.Spinner; 

public class MainActivity extends AppCompatActivity { 
    ArrayList<Post> archivo=new ArrayList<Post>(); 
    ArrayList<String> titulos=new ArrayList<String>(); 
    public ArrayAdapter<String> spinnerArrayAdapter; 
    private static final String TAG= MainActivity.class.getSimpleName(); 
    private class GetDBConnection extends AsyncTask<Integer, Void, String>{ 
     @Override 
     protected String doInBackground(Integer... params) { 
      try{ 
       Connection conn= DBConnection.getInstance().getConnection(); 
       Statement st= conn.createStatement(); 
       String sql=("SELECT * FROM posts"); 
       ResultSet rs=st.executeQuery(sql); 
       while(rs.next()) { 
        int id = rs.getInt("Id"); 
        String title = rs.getString("Title"); 
        String body = rs.getString("Body"); 
        String date = rs.getString("Date"); 
        Post post = new Post(id, title, body, date); 
        archivo.add(post); 
        System.out.println(archivo); 
       } 
       Log.d(TAG,"Terminado"); 
      }catch(SQLException e){ 
       e.printStackTrace(); 
      } 
      return "Valido"; 
     } 

     @Override 
     protected void onPostExecute(String result) { 
      Spinner spinner=(Spinner) findViewById(R.id.spinner); 
      spinner.setVisibility(View.VISIBLE); 
      for (Post i:archivo) { 
       titulos.add(i.getTitle()); 
      } 
      TextView title=(TextView) findViewById(R.id.title); 
      TextView body=(TextView) findViewById(R.id.body); 
      title.setVisibility(View.VISIBLE); 
      body.setVisibility(View.VISIBLE); 
      TextView connection=(TextView) findViewById(R.id.connection); 
      connection.setVisibility(View.INVISIBLE); 
      spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 
       @Override 
       public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 
        spinnerArrayAdapter.notifyDataSetChanged(); 
        Post resultado=archivo.get(position); 
        title.setText(resultado.getTitle()); 
        body.setText(resultado.getBody()); 
       } 

       @Override 
       public void onNothingSelected(AdapterView<?> parent) { 
        spinnerArrayAdapter.notifyDataSetChanged(); 
        Post resultado=archivo.get(0); 
        title.setText(resultado.getTitle()); 
        body.setText(resultado.getBody()); 
       } 
      }); 

     } 
    } 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     new GetDBConnection().execute(0); 
     Spinner spinner=(Spinner) findViewById(R.id.spinner); 
     spinnerArrayAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, titulos); 
     spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
     spinner.setAdapter(spinnerArrayAdapter); 
     spinner.setSelection(1); 
     System.out.println(archivo); 



    } 


} 

И это мой XML-код:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:id="@+id/activity_main" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:paddingBottom="@dimen/activity_vertical_margin" 
    android:paddingLeft="@dimen/activity_horizontal_margin" 
    android:paddingRight="@dimen/activity_horizontal_margin" 
    android:paddingTop="@dimen/activity_vertical_margin" 
    tools:context="com.example.lagarto.blog.MainActivity"> 



    <TextView 
     android:layout_width="400dp" 
     android:layout_height="50dp" 
     android:text="Hello World!" 
     android:textSize="30dp" 
     android:textAlignment="center" 
     android:layout_alignParentEnd="true" 
     android:id="@+id/title" 
     android:layout_marginTop="40dp" 
     android:visibility="invisible" 
     /> 
    <TextView 
     android:layout_width="400dp" 
     android:layout_height="500dp" 
     android:text="Hello World!" 
     android:textSize="16dp" 
     android:layout_marginTop="100dp" 
     android:layout_alignParentEnd="true" 
     android:id="@+id/body" 
     android:visibility="invisible" 
     /> 

    <Spinner 
     android:layout_width="400dp" 
     android:layout_height="50dp" 
     android:layout_alignParentTop="true" 
     android:layout_centerHorizontal="true" 
     android:id="@+id/spinner" 
     android:textSize="20dp" 
     android:visibility="invisible" 
     android:backgroundTint="@color/colorPrimaryDark" 
     android:textAlignment="center" 
     /> 

    <TextView 
     android:text="Waiting for connection please wait" 
     android:layout_width="400dp" 
     android:layout_height="100dp" 
     android:textSize="30dp" 
     android:textAlignment="center" 
     android:layout_marginTop="150dp" 
     android:id="@+id/connection" /> 


</RelativeLayout> 
+1

Я думаю, было бы лучше, если бы вы положили 'spinner.setOnItemSelectedListener' на' onCreate'. Вы должны сконцентрироваться на фоновом процессе для получения данных. – cipley

+0

Это не исправляет ошибку:/ –

+0

Нечетный ... вы получаете какой-либо logcat после завершения 'onPostExecute'? – cipley

ответ

0

Хорошо, вот мои оценки:

TL; DR:

Вы пытались обновить пользовательский интерфейс в фоновом потоке.

Объяснение:

Это ваш кусок кода на onCreate

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    new GetDBConnection().execute(0); 
    Spinner spinner=(Spinner) findViewById(R.id.spinner); 
    spinnerArrayAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, titulos); 
    spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
    spinner.setAdapter(spinnerArrayAdapter); 
    spinner.setSelection(1); 
    System.out.println(archivo); 
} 

несколько указателей на этой основе:

  • Вы назвали GetDBConnection, прежде чем ваш кок является даже готов. Ваш GetDBConnection будет запускаться асинхронно в фоновом режиме, поэтому пока вы извлекаете свои данные иonItemSelectedListener для вашего счетчика (я объясню позже), вы создали условие гонки, когда вы настраиваете свой счетчик.
  • Кажется, что ваш спиннер заселен, но это не было хорошей практикой.
  • Затем вы задаете выбор, был ли асинхронный вызов завершен или нет, используя spinner.setSelection(1);. Я забыл, нужно ли это исключать или нет.

Теперь на вашем onPostExecute кусок кода:

@Override   
protected void onPostExecute(String result) { 
    Spinner spinner=(Spinner) findViewById(R.id.spinner); 
    spinner.setVisibility(View.VISIBLE); 
    for (Post i:archivo) { 
     titulos.add(i.getTitle()); 
    } 
    TextView title=(TextView) findViewById(R.id.title); 
    TextView body=(TextView) findViewById(R.id.body); 
    title.setVisibility(View.VISIBLE); 
    body.setVisibility(View.VISIBLE); 
    TextView connection=(TextView) findViewById(R.id.connection); 
    connection.setVisibility(View.INVISIBLE); 
    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 
     @Override 
     public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 
      spinnerArrayAdapter.notifyDataSetChanged(); 
      Post resultado=archivo.get(position); 
      title.setText(resultado.getTitle()); 
      body.setText(resultado.getBody()); 
     } 
     @Override 
     public void onNothingSelected(AdapterView<?> parent) { 
      spinnerArrayAdapter.notifyDataSetChanged(); 
      Post resultado=archivo.get(0); 
      title.setText(resultado.getTitle()); 
      body.setText(resultado.getBody()); 
     } 
    }); 
} 
  • Если вы хотите обновить элементы вашего Прядильщиков на лету, вы должны также включать в себя методы для обновления (добавление, удаление или обновление) Элементы списка в вашем адаптере.
  • Как я упоминал ранее, помещение слушателя в AsyncTask является, пожалуй, применимым, а не хорошей практикой. Не говоря уже о том, что вы также пытаетесь изменить пользовательский интерфейс (устанавливаете значения TextView). Это приведет к ошибке, потому что ваш вызов не связан с потоком пользовательского интерфейса.Вот почему я сказал, что вы должны сосредоточить AsyncTask на выборку данных только

Если у вас есть свой собственный адаптер, вот мой пользовательский адаптер, который способен обрабатывать обновление данных:

public abstract class CustomListAdapter<T> extends BaseAdapter { 
    protected List<T> mData = new ArrayList<>(); 
    protected LayoutInflater mInflater; 
    protected ViewHolder holder; 

    /*truncated*/ 

    public void addItem(T item){ 
     mData.add(item); 
     notifyDataSetChanged(); 
    } 

    public void clear(){ 
     mData = new ArrayList<>(); 
     notifyDataSetChanged(); 
    } 

    public void deleteItem(int position){ 
     mData.remove(position); 
     notifyDataSetChanged(); 
    } 

    public void fill(Collection<T> items){ 
     mData.addAll(items); 
     notifyDataSetChanged(); 
    } 
} 

Конечно, это всего лишь пример.

Резюме:

Попробуйте обновить свой код следующим образом:

//Declare your elements here first; 

TextView title; 
TextView body; 
TextView connection; 
Spinner spinner; 

private class GetDBConnection extends AsyncTask<Integer, Void, String>{ 
    @Override 
    protected String doInBackground(Integer... params) { 
     try{ 
      Connection conn= DBConnection.getInstance().getConnection(); 
      Statement st= conn.createStatement(); 
      String sql=("SELECT * FROM posts"); 
      ResultSet rs=st.executeQuery(sql); 
      while(rs.next()) { 
       int id = rs.getInt("Id"); 
       String title = rs.getString("Title"); 
       String body = rs.getString("Body"); 
       String date = rs.getString("Date"); 
       Post post = new Post(id, title, body, date); 
       archivo.add(post); 
       System.out.println(archivo); 
      } 
      Log.d(TAG,"Terminado"); 
     }catch(SQLException e){ 
      e.printStackTrace(); 
     } 
     return "Valido"; 
    } 

    @Override 
    protected void onPostExecute(String result) { 
     /* 
      all code that changes your UI should resides in the UI Thread. This is still in Background Thread. 
     */ 
     //Spinner spinner=(Spinner) findViewById(R.id.spinner); --> this is also unneccessary 
     //spinner.setVisibility(View.VISIBLE); 

     /* 
      something like this is possible as long as it doesn't change your UI. 
     */ 
     for (Post i:archivo) { 
      titulos.add(i.getTitle()); 
      /* 
      - update your Adapter List elements here. 
      */ 
     } 
     // - also call your adapter notifyDataSetChanged here, if neccessary. 

     //TextView title=(TextView) findViewById(R.id.title); --> unneccessary! 
     //TextView body=(TextView) findViewById(R.id.body); --> unneccessary! 
     //title.setVisibility(View.VISIBLE); 
     //body.setVisibility(View.VISIBLE); 
     //TextView connection=(TextView) findViewById(R.id.connection); --> unneccessary! 
     //connection.setVisibility(View.INVISIBLE); 

     /* 
      instead, you can call another method that resides in the UI Thread 
     */ 
     // updateUI(); 
     /* 
      or, execute them under runOnUIThread() 
     */ 
     runOnUIThread(new Runnable(){ 
      @Override 
      public void run(){ 
       spinner.setVisibility(View.VISIBLE); 
       title.setVisibility(View.VISIBLE); 
       body.setVisibility(View.VISIBLE); 
       connection.setVisibility(View.INVISIBLE); 
      } 
     }); 
    } 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     /* 
      you should initiate ALL your UI elements on the onCreate() 
     */ 
     spinner=(Spinner) findViewById(R.id.spinner); 
     title=(TextView) findViewById(R.id.title); 
     body=(TextView) findViewById(R.id.body); 
     connection=(TextView) findViewById(R.id.connection); 
     spinnerArrayAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, titulos); 
     spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
     /* 
      then, set your listeners 
     */ 
     spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 
      @Override 
      public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 
       //spinnerArrayAdapter.notifyDataSetChanged(); --> this is unneccessary 
       Post resultado=archivo.get(position); 
       title.setText(resultado.getTitle()); 
       body.setText(resultado.getBody()); 
      } 
      @Override 
      public void onNothingSelected(AdapterView<?> parent) { 
       //spinnerArrayAdapter.notifyDataSetChanged(); --> this is unneccessary 
       Post resultado=archivo.get(0); 
       title.setText(resultado.getTitle()); 
       body.setText(resultado.getBody()); 
      } 
     }); 
     spinner.setAdapter(spinnerArrayAdapter); 
     System.out.println(archivo); 

     new GetDBConnection().execute(0); // --> After all has been set, then execute your AsyncTask. 
    } 

    private void updateUI(){ 
     spinner.setVisibility(View.VISIBLE); 
     title.setVisibility(View.VISIBLE); 
     body.setVisibility(View.VISIBLE); 
     connection.setVisibility(View.INVISIBLE); 
    } 
} 

Надеется, что это помогает!